遅い二次アルゴリズムと高速ハッシュマップについての簡単な説明

遅い二次アルゴリズムと高速ハッシュマップについての簡単な説明

[[424110]]

こんにちは、みんな!昨日、プログラミング面接の準備をしていて、アルゴリズムの基礎を学ぼうとしている友人とチャットをしていました。

私たちは話しました二次時間二次時間そして線形時間線形時間アルゴリズムの話題については、ここでそれについて書くのは楽しいだろうと思いました。なぜなら、二次時間アルゴリズムを避けることは、面接で重要であるだけでなく、実生活でそれについて知っておくと便利な場合があるからです。 「二次時間アルゴリズム」とは何かについては後で簡単に説明します :)

ここで議論する 3 つの事項は次のとおりです。

  1. 二次関数は一次関数よりもはるかに遅い
  2. ハッシュマップを使うことで、二次アルゴリズムを線形アルゴリズムに変換できる場合がある。
  3. これは、ハッシュマップの検索が非常に高速であるためです (即時検索!)

数学の専門用語は避け、実際のコード例と、実際にどれくらい速いか遅いかに焦点を当てたいと思います。

目標問題: 2つのリストの共通部分を見つける

2 つの数値リストの共通部分を取得するという、簡単なインタビュー形式の問題について説明しましょう。 たとえば、 intersect([1,2,3], [2,4,5]) [2]を返します。

この問題には現実世界への応用もいくつかあります。2 つの ID リストの正確な交差を必要とする実際のプログラムを想像してみてください。

「明白な」解決策:

2 つのリストの共通部分を取得するコードを書いてみましょう。以下は、この要件を実装するquadratic.pyという名前のプログラムです。

  1. import sys
  2. # 实际运行的代码
  3. def intersection ( list1 , list2 ):
  4. result = []
  5. for x in list1 :
  6. for y in list2 :
  7. if x == y :
  8. result . append ( y )
  9. return result
  10. # 一些样板,便于我们从命令行运行程序,处理不同大小的列表
  11. def run ( n ):
  12. # 定义两个有 n + 1 个元素的列表
  13. list1 = list ( range ( 3 , n )) + [ 2 ]
  14. list2 = list ( range ( n + 1 , 2 * n )) + [ 2 ]
  15. # 取其交集并输出结果
  16. print ( list ( intersection ( list1 , list2 )))
  17. # 使用第一个命令行参数作为输入,运行程序
  18. run ( int ( sys . argv [ 1 ]))

プログラムの名前がquadratic.pyなのは、 list1list2のサイズがnの場合、内部ループ ( if x == y ) がn^2回実行されるためです。数学では、 x^2のような関数は「二次」関数と呼ばれます。

quadratic.pyはどれくらい遅いですか?

このプログラムを異なる長さのリストで実行すると、2つのリストの共通部分は常に同じになります: [2]

  1. $ time python3 quadratic . py 10
  2. [ 2 ]
  3. real 0m0.037s
  4. $ time python3 quadratic . py 100
  5. [ 2 ]
  6. real 0m0.053s
  7. $ time python3 quadratic . py 1000
  8. [ 2 ]
  9. real 0m0.051s
  10. $ time python3 quadratic . py 10000 # 10 , 000
  11. [ 2 ]
  12. real 0m1.661s

これまでのところ順調です。プログラムの実行時間は依然として 2 秒未満です。

次に、それぞれ 100,000 要素の 2 つのリストでプログラムを実行しましたが、長い時間待たなければなりませんでした。結果は次のとおりです。

  1. $ time python3 quadratic . py 100000 # 100 , 000
  2. [ 2 ]
  3. real 2m41.059s

かなり遅いですね!これには合計 160 秒かかり、10,000 要素で実行した場合 (1.6 秒) のほぼ 100 倍の時間がかかりました。したがって、ある時点以降、リストを 10 倍大きくするたびに、プログラムの実行にかかる時間が約 100 倍長くなることがわかります。

このプログラムを 1,000,000 個の要素で実行しようとはしませんでした。100 倍の時間がかかることがわかっていたからです (おそらく 3 時間程度)。こんな時間はないよ!

おそらくこれで、2 次時間アルゴリズムがなぜ問題になるのかがお分かりいただけたと思います。この非常に単純なプログラムでさえ、すぐに非常に遅くなる可能性があるのです。

高速バージョン: linear.py

さて、プログラムの簡単なバージョンを書いてみましょう。まずプログラムがどのようなものかを示し、その後分析します。

  1. import sys
  2. # 实际执行的算法
  3. def intersection ( list1 , list2 ):
  4. set1 = set ( list1 ) # this is a hash set
  5. result = []
  6. for y in list2 :
  7. if y in set1 :
  8. result . append ( y )
  9. return result
  10. # 一些样板,便于我们从命令行运行程序,处理不同大小的列表
  11. def run ( n ):
  12. # 定义两个有 n + 1 个元素的列表
  13. list1 = range ( 3 , n ) + [ 2 ]
  14. list2 = range ( n + 1 , 2 * n ) + [ 2 ]
  15. # 输出交集结果
  16. print ( intersection ( list1 , list2 ))
  17. run ( int ( sys . argv [ 1 ]))

(これは Python を使用する最も慣用的な方法ではありませんが、Python を知らない人でも理解しやすいように、Python のアイデアをあまり使用せずにコードを書きたかったのです)

ここでは、低速バージョンとは異なる 2 つのことを行います。

  1. list1 set1という名前のセットに変換します。
  2. 2つのforループではなく1つのforループのみを使用する

linear.pyプログラムの速さを見てみましょう

このプログラムがなぜ高速なのかを説明する前に、実際に高速であることを示すために、いくつかの大きなリストでプログラムを実行してみましょう。ここでは、プログラムが 10 から 10,000,000 までのサイズのリストに対して順番に実行されている様子が示されています。 (前のプログラムは 100,000 要素で非常に遅くなり始めたことを思い出してください)

  1. $ time python3 linear . py 100
  2. [ 2 ]
  3. real 0m0.056s
  4. $ time python3 linear . py 1000
  5. [ 2 ]
  6. real 0m0.036s
  7. $ time python3 linear . py 10000 # 10 , 000
  8. [ 2 ]
  9. real 0m0.028s
  10. $ time python3 linear . py 100000 # 100 , 000
  11. [ 2 ]
  12. real 0m0.048s <-- quadratic . py took 2 minutes in this case ! we 're doing it in 0.04 seconds now!!! so fast!
  13. $ time python3 linear.py 1000000 # 1,000,000
  14. [2]
  15. real 0m0.178s
  16. $ time python3 linear.py 10000000 # 10,000,000
  17. [2]
  18. real 0m1.560s

非常に大きなリストでlinear.pyを実行する

これを非常に大きなリスト (100 億 / 10,000,000,000 要素) で実行しようとすると、別の問題が発生します。十分に高速ですが (リストは 4.2 秒かかったリストの 100 倍しかないため、おそらく 420 秒以内に終了できるはずです)、コンピューターにはリストのすべての要素を格納するのに十分なメモリがないため、終了する前にプログラムがクラッシュします。

  1. $ time python3 linear . py 10000000000
  2. Traceback ( most recent call last ):
  3. File "/home/bork/work/homepage/linear.py" , line 18 , in < module >
  4. run ( int ( sys . argv [ 1 ]))
  5. File "/home/bork/work/homepage/linear.py" , line 13 , in run
  6. list1 = [ 1 ] * n + [ 2 ]
  7. MemoryError
  8. real 0m0.090s
  9. user 0m0.034s
  10. sys 0m0.018s

ただし、この記事ではメモリ使用量については説明していないため、この問題は無視できます。

では、なぜlinear.pyは高速なのでしょうか?

ここで、 linear.pyが高速である理由を説明します。

もう一度コードを見てみましょう:

  1. def intersection ( list1 , list2 ):
  2. set1 = set ( list1 ) # this is a hash set
  3. result = []
  4. for y in list2 :
  5. if y in set1 :
  6. result . append ( y )
  7. return result

list1list2どちらも約 10,000,000 個の異なる要素を持つリストであるとします。この要素数は非常に大きいと言えます。

では、なぜそんなに速く走るのでしょうか?ハッシュマップのせいだ! ! !

ハッシュマップの検索は瞬時に行われます(「一定時間」)

プログラムのクイック バージョンのifステートメントを見てみましょう。

  1. if y in set1 :
  2. result . append ( y )

set1 1,000 万の要素が含まれている場合、 if y in set1検索は、 set1に 1,000 の要素が含まれている場合よりも遅くなると思われるかもしれません。しかし、そうではありません! set1がどれだけ大きくても、必要な時間は基本的に同じです (超高速)。

これは、 set1がハッシュ セットであり、キーのみで値のないハッシュマップ (ハッシュ テーブル) 構造であるためです。

この記事ではハッシュマップ検索がなぜ瞬時に行われるのかについては説明しません。ただし、ハッシュ テーブルとハッシュ関数に関する Vaidehi Joshi の素晴らしい basecs シリーズでは、ハッシュマップ検索がなぜ瞬時に行われるのかについて説明しています。

偶然の二次方程式: 現実世界における二次方程式アルゴリズム!

2 次時間アルゴリズムは非常に遅く、私たちが目にする問題は現実世界で実際に遭遇したものです。Nelson Elhage は、Accidentally Quadratic という素晴らしいブログを運営しており、そこには、誤って 2 次時間でコードを実行し、パフォーマンスの問題を引き起こした事例が紹介されています。

二次時間アルゴリズムが突然現れるかもしれない

二次時間アルゴリズムの奇妙なところは、少数の要素 (1000 個など) で実行すると、それほど悪くないように見えることです。そんなに遅くないよ!しかし、1,000,000 個の要素を指定すると、実行に文字通り数時間かかります。

したがって、特に線形時間アルゴリズムを簡単に記述できる場合 (ハッシュマップを使用するなど) は、誤って二次時間アルゴリズムを使用することを避けるために、これについてさらに学習する価値があると思います。

いつもちょっと魔法のようなハッシュマップを感じさせてくれる

ハッシュマップは確かに魔法ではありません (ハッシュマップ検索がなぜ瞬時に行われるのかを知ることができます。本当にすごいです!) が、いつも少し魔法のような気分になり、ハッシュマップを使用してプログラムを高速化するたびに幸せな気持ちになります :)

<<:  AI: データ駆動型企業への次のステップ

>>:  スマートエコノミーの時代において、人工知能技術をどのように活用して、より多くの技術的利益をもたらすことができるのでしょうか?

ブログ    
ブログ    
ブログ    
ブログ    

推薦する

...

将来の成長の原動力は?ビッグデータ+人工知能が浸透し、私たちの生活を変える

画像ソース: Unsplash新世代情報技術の急速な発展に伴い、コンピューティング能力、データ処理能...

人工知能の急速な成長がアジア太平洋地域のデータセンター市場を牽引する

JLLの新しいグローバルデータセンター展望によると、クラウドコンピューティングと人工知能(AI)の大...

...

5G、Wi-Fi 6、AIがいかにしてよりスマートなホームエクスペリエンスを実現するか

[[335277]]家全体のスマートホームライフが実現するまでには、まだ時間がかかりそうですが、スマ...

RNN の理論から PyTorch まで

RNN とは何か、どこで使用されているか、どのように前方および後方に伝播するか、そして PyTorc...

AI スタートアップはどうすれば成功できるのでしょうか?ガートナー:「以下の点が不可欠」

[[430175]]デジタル変革の波を受けて、さまざまな新興技術が急速に応用され、普及してきました...

...

IoT人工知能の将来動向

AI と IoT の融合は拡大し続けており、刺激的な将来のトレンドと機会への道を切り開いています。 ...

...

新しいAI技術がアルツハイマー病の薬のターゲット発見に役立つ

人工知能は10年以上にわたって新薬の発見と開発に使用されてきました。しかし、最近の AI 技術と研究...

AIは小売市場の衰退を防ぐことができるか?

デジタル時代の到来により、私たちの生活は急速に変化しました。買い物の仕方も、近所のショッピングモール...

AI モデルの 3 種類のバイアスとその修正方法

自動化された意思決定ツールは組織内でますます一般的になりつつあります。しかし、顔認識システムからオン...

兵馬俑は「Subject Three」を演奏したが、これは予想外のことだった

ご家族の皆さん、世界中で人気の魔法のダンス「Subject Three」、まさか兵馬俑も踊り始めると...