小さなアルゴリズム列の始まり:DFSのフィボナッチ数列

小さなアルゴリズム列の始まり:DFSのフィボナッチ数列

序文

  本日より、ソフトウェアアルゴリズムを学んでいた時期のトピックやまとめをご紹介します。私はソフトウェアクラスでもACMでもないので、LeetcodeLinkcodeについて説明することを期待しないでください本当に無力です難しい質問に遭遇する


ここに画像の説明を挿入

  コンピュータの専門用語についてはめったに使用せず、直感的なデータを使用して反映します〜

  若い人たちは、コードの道徳性さまざまな剪定の最適化、さまざまな記憶方法、さまざまな終了条件、咳、咳、咳...(吐血)を話しません

CSDN(Φ-Φ)乾杯つロ

DFSの簡単な紹介

  今日は** DFS(深さ優先探索)**から始めました。最初に学習を始めたとき、先生からテスト用の質問がありました。DFS、恥ずかしかったですか?たぶんそれは基本で言及されたか、C言語を学ぶとき、単純な構造はまだ可能です。後で質問を始めますね

  しかし今のところ、実際には、アルゴリズムによって補完された、決定ロジックベースのプルーニング最適化のアイデアを最初にルーチン化するのはDFSです

  さて、簡単に紹介しましょう。深さ優先探索DFSと幅優先探索BFSは、2つの非常に重要なソフトウェアアルゴリズムです。最短経路、グローバル検索、その他の最適化問題など、グラフ理論には多くのアプリケーションがあります。

  深さ優先、つまり、現在確立されている検索戦略の下で、暗闇への1つの方法で続行します。それがうまくいかない場合は、現在のループを終了し、検索戦略を変更して、終了点が見つかるまでループを続けると言えます。マウスが迷路を歩いているようなものではありませんか。

ここに画像の説明を挿入
  意味はわかりやすいですが、3つのポイントがあると思います。

  1. 1つ目は、言うまでもなくコアアルゴリズムである検索戦略です。

  2. 2つ目は、ループの前後のパラメータの転送です。つまり、移動した道路を使用したり、障害のある道路を通過して、直接移動せずに他のn個の同様の道路を通過したりせず、時間とスペースを節約し、一部を通過します。変数の。

  3. 3つ目は終了条件で、終了条件はありません。無限ループです。ハッピーエンドです。

  上記のキーポイントは今後のコンテンツに徐々に反映されていきます〜あまり心配する必要はなく、小さな百科事典になります。


DFSを使用したフィボナチの実装

  今日はフィボナッチ(フィボナッチ数列)から始めて、DFSをみんなに紹介します。

  使用される環境はWindows10 + Python3.7です。

  文法はとてもシンプルで、それ自体が説明言語であり、理解しやすいものです。
  フィボナッチ数列は非常に一般的です:1、1、2、3、5、...

  3番目の項目から始まり、各項目は最初の2つの項目の合計です。n番目の項目を要求するとします。n-1とn-2番目の項目を知る必要があり、n-1番目の項目を要求し、さらにn-2番目とn-3番目の項目も知る必要があります。それは継続的なループプロセスです。それはいつ頭ですか?

  1番目と2番目の項目は両方とも1であることがわかっているので、これら2つの項目に戻るときは、1を直接返しますまるで迷路のようです。各階に部屋があります。各階の部屋には上層階を開くために必要な鍵があります。最上階の部屋にはオレオがあります。どうすればオレオを手に入れることができますか?

ここに画像の説明を挿入
  直感的思考:最下階に行って最下層の2階の鍵を手に入れるだけで、まっすぐ上に上がり、この期間中はドアを開けたままにして、最上階の部屋を開けるまで鍵を集めることができます。 。

  コードを見てください:

def fibonaci():
    """
    Function: get n_th value in Fibonacci_array using DFS
    Returns: None
    """
    import time
    # input the index
    n=int(input())
    # core function
    def dfs(x):
        if x == 1 or x == 2:
            return 1
        else:
            # recursion step
            return dfs(x - 1) + dfs(x - 2)
    # record processing time
    start=time.time()
    # print answer
    print(dfs(n))
    print("Using {:.5f} s".format(time.time() - start))
    return

>>> fibonaci()
20
6765
Using 0.01405 s
>>> fibonaci()
35
9227465
Using 2.22722 s

  上記は、私たちの考えに従って書かれたn番目のフィボナッチ数列を解くためのDFSの機能です。タイムライブラリは、プログラムの実行時間を計算することです。コア機能は、第1項または第2項に再帰することです。1を直接返します。それ以外の場合、最初の2つの項目に対応する値は、関数を介して再帰的に解かれます。

  ただし、nが大きすぎると、結果が遅くなります。35期を解くのに2.22秒かかりましたが、これはたまらないです。

  その理由は、n番目の項を見つけるたびに、0〜n-1の項を見つける必要があり、このプロセスはサブプロセスでも同じです。つまり、n-1番目の項が取得されると、時間計算量が大きくなります。アルゴリズムの増加はNとともに増加します。の増加は指数関数的成長であり、時間計算量はO(2 ^ n)、つまり2のn乗であり、アルゴリズムのプロセスは二分木を横断していると見なすことができます。 。

ここに画像の説明を挿入

DFSでのメモリ検索

  行列乗算への変換や高速べき乗剰余の適用、メモリ検索など、改善する方法はたくさんあります。

  メモリ検索は、DFSで一般的に使用される最適化されたプルーニング戦略です。プルーニングの意味はここでは非常に鮮明です。つまり、不要なノードを削除し、そこで繰り返さないことです。

  上記の関数のn番目の項とn-1番目の項を解くプロセスは基本的に同じであることが簡単にわかります。つまり、プログラムは多くの無駄な作業を行っています。中間プロセスを記録すると、解決プロセス。値を再度直接呼び出す必要がある場合は、効率を向上させることができます。つまり、時間のスペースを使用します。

  早くやれよ!

def fibonaci():
    """
    Function: get n_th value in Fibonacci Array using DFS with memory search
    Returns: None
    """
    import time
    # input the index
    n=int(input())
    # store intermediate results
    ans=[False for i in range(n + 1)]
    # core function
    def dfs(x):
        nonlocal ans
        if ans[x]:
            return ans[x]
        if x == 1 or x == 2:
            ans[x] = 1
            return 1
        else:
            ans[x] = dfs(x - 1) + dfs(x - 2)
            return ans[x]
    # record processing time
    start=time.time()
    # print answer
    print(dfs(n))
    print("Using {:.5f} s".format(time.time() - start))
    return

>>> fibonaci()
35
9227465
Using 0.00751 s
>>> fibonaci()
50
12586269025
Using 0.00795 s
>>> fibonaci()
100
354224848179261915075
Using 0.01003 s

  メモ化された検索方法では、35番目の項を解くときに0.01153しか使用されなかったことがわかります。実際の時間計算量は、基本的に線形O(N)レベル維持されます

ここに画像の説明を挿入

リトルトリック

  実際、再帰的方法は、関数の再帰的スタックの数によって制限されます。デフォルトは1000です。非再帰的な形式で解決できますが、今日の範囲ではないため、紹介しません。自分で関連情報を確認できます〜

  さらに、ちょっとしたコツがあります。フィボナッチ数列のn番目の項を解く必要がある場合もありますが、nは大きすぎません(50未満)。次に、簡潔な次のより高速なラムダ無名関数メソッドを使用できます。 〜

# Lambda function definition
Fibo = lambda x: 1 if x == 1 or x == 2 else Fibo(x-1) + Fibo(x-2)
# test
>>> Fibo(20)
6765
>>> Fibo(35)
9227465

  実際、メモ化されていない検索のDFSコア関数を匿名関数に単純化することです。これは将来のトピックで頻繁に使用されるため、より便利だと思います。

  今日はここにいます。質問やコメントがある人は、ブログや公開アカウントで質問することができ、時間内に返信します。


WeChat

CSDNブログ

ナイフでハクトウワシに来てください〜

参照

[1]アルゴリズムの小さな列始まり:DFSのフィボナチシリーズ

おすすめ

転載: blog.csdn.net/weixin_40519529/article/details/113081416