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

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

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

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

[[424052]]

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

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

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

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

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

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

「明白な」解決策:

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

  1. インポートシステム
  2. # 実際の実行コード
  3. 交差を定義します(リスト1、リスト2):
  4. 結果 = []
  5. list1xの場合:
  6. リスト2yについて:
  7. x == yの場合:
  8. 結果.append(y)
  9. 結果を返す
  10. # コマンドラインからプログラムを実行し、さまざまなサイズのリストを扱いやすくするための定型文
  11. def run(n):
  12. # n+1 個の要素を持つ 2 つのリストを定義する
  13. リスト1 = リスト(範囲(3, n)) + [2]
  14. リスト2 = リスト(範囲(n+1, 2*n)) + [2]
  15. # 交差を取って結果を出力します
  16. print(リスト(交差(リスト1, リスト2)))
  17. # 最初のコマンドライン引数を入力として使用してプログラムを実行します
  18. 実行( int (sys.argv[1]))

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

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

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

  1. $時間python3 quadratic.py 10
  2. [2]
  3. 実数0分0.037秒
  4. $時間python3 quadratic.py 100
  5. [2]
  6. 実数0分0.053秒
  7. $時間python3 quadratic.py 1000
  8. [2]
  9. 実数0分0.051秒
  10. $時間python3 quadratic.py 10000 # 10,000
  11. [2]
  12. 実数0分1.661秒

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

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

  1. $時間python3 quadratic.py 100000 # 100,000
  2. [2]
  3. 実数2分41秒059

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

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

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

高速バージョン: linear.py

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

  1. インポートシステム
  2. # 実際に実行されるアルゴリズム
  3. 交差を定義します(リスト1、リスト2):
  4. set1 = set (list1) # これはハッシュセットです 
  5. 結果 = []
  6. リスト2yについて:
  7. yがset1にある場合:
  8. 結果.append(y)
  9. 結果を返す
  10. # コマンドラインからプログラムを実行し、さまざまなサイズのリストを扱いやすくするための定型文
  11. def run(n):
  12. # n+1 個の要素を持つ 2 つのリストを定義する
  13. リスト1 = 範囲(3, n) + [2]
  14. リスト2 = 範囲(n+1, 2*n) + [2]
  15. # 交差結果を出力する
  16. print(交差(リスト1, リスト2))
  17. 実行( 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. $時間python3 linear.py 100
  2. [2]
  3. 実数0分0.056秒
  4. $時間python3 linear.py 1000
  5. [2]
  6. 実数0分0.036秒
  7. $時間python3 linear.py 10000 # 10,000
  8. [2]
  9. 実数0分0.028秒
  10. $時間python3 linear.py 100000 # 100,000
  11. [2]
  12. real 0m0.048s < -- この場合、quadratic.py に 2 分かかりました。今では 0.04 秒で実行しています。とても速いです!  
  13. $時間python3 linear.py 1000000 # 1,000,000
  14. [2]
  15. 実数0分0.178秒
  16. $時間python3 linear.py 10000000 # 10,000,000
  17. [2]
  18. 実数0分1.560秒

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

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

  1. $時間python3 linear.py 10000000000
  2. トレースバック(最新の呼び出しが最後):
  3. ファイル"/home/bork/work/homepage/linear.py" 、行 18 <module>
  4. 実行( int (sys.argv[1]))
  5. ファイル「/home/bork/work/homepage/linear.py」、13行目、実行
  6. リスト1 = [1] * n + [2]
  7. メモリエラー
  8. 実数0分0.090秒
  9. ユーザー0m0.034s
  10. システム 0分0.018秒

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

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

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

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

  1. 交差を定義します(リスト1、リスト2):
  2. set1 = set (list1) # これはハッシュセットです 
  3. 結果 = []
  4. リスト2yについて:
  5. yがset1にある場合:
  6. 結果.append(y)
  7. 結果を返す

list1 と list2 はどちらも約 10,000,000 個の一意の要素を持つリストだとします。これは非常に多い数です。

では、なぜこんなに速く実行できるのでしょうか? それはハッシュマップのおかげです!!!

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

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

  1. yがset1にある場合:
  2. 結果.append(y)

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

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

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

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

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

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

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

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

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

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

<<:  インテリジェントコンピューティングセンター構築の「サンゴ礁」と「灯台」

>>:  Alimama は曲率空間学習フレームワークと連合学習ソリューションをオープンソース化し、共通の進歩のために AI 技術を一般に公開します。

ブログ    
ブログ    
ブログ    

推薦する

Google のロボットアームはハンカチなど、柔らかいものも硬いものもつかむことができます。 ICRA 2021が承認されました

現在、ロボットに関する研究は、主に特定の形状の物体を掴むためのロボットアームの設計に焦点を当てていま...

マスクとイリヤのプライベートメールがクロードによって解読され、OpenAIの暗号化された情報が公開され、Googleが損害を被った

OpenAIとマスク氏は激しく議論していたが、誤ってClaude 3の新しいスキルを公開してしまった...

Didi、AI技術を活用して交通問題を解決するTraffic Brainをリリース

滴滴出行は1月25日、2018年スマート交通サミットでスマート交通戦略製品「Traffic Brai...

MITとワトソン研究所のチームが、ジェスチャーを見るだけで音楽を完璧に再現する最新のAIを発表

この記事はLeiphone.comから転載したものです。転載する場合は、Leiphone.com公式...

スマートシティ交通ソリューションへのテクノロジーの影響

インテリジェントな交通管理システムは、スマートシティの開発に欠かせない要素です。具体的には、スマート...

...

...

...

人工知能はノーベル賞レベルにまで発展した

人工知能(AI)はノーベル賞の領域に入った。最近の研究により、人々にこのような感覚を与えるものが生み...

今後5年間で人気が高まり、就職時の給与も高くなる3つの専攻

大学で何を専攻するかは、慎重に考える必要があります。結局のところ、大学の専攻の選択は私たちの将来の発...

...

...

...

レゴブロックを積み上げるように: ニューラルネットワークの数学をゼロから説明する

ニューラル ネットワークは、線形モジュールと非線形モジュールを巧みに組み合わせたものです。これらのモ...

WindowsとOfficeは使いやすく、大型モデルのインテリジェントエージェントはコンピュータを操作するのにとてもクールです

AI アシスタントの将来について語るとき、アイアンマン シリーズに登場する魅力的な AI アシスタン...