見出し画像

JavaScriptで学ぶアルゴリズム②[2分探索]

外資系企業でソフトウェアエンジニアをしております、タロイモと言います。今日もよろしくお願いします。

前回は、O(n)とO(1)アルゴリズムの紹介をしました。

今回は、O(log n)アルゴリズムを紹介いたします。

O(log n)

O(log n)アルゴリズムはデータ量が増えても計算量が変わらないという特徴を持つので、素晴らしいアルゴリズムと言えるでしょう。

スクリーンショット 2020-08-29 12.40.02

O(log n)アルゴリズムでは、2分探索(バイナリーサーチ)が有名です。

2分探索は、予めソート(整理)してあるデータから特定の値を探す時に利用します。

辞書で例えるとわかりやすいかもしれません。

50重音順に並んだ辞書があるとします。

「あ」「い」「う」「え」「お」、、、「わ」「を」「ん」で終わる辞書です。

スクリーンショット 2020-08-29 13.00.26


ここで「ラーメン」という言葉を探してみるとします。

ラーメンの「ら」を調べる時、私たちはパッと「ら」のページを開くことができます。

スクリーンショット 2020-08-29 12.53.17

しかし、コンピューターはそうはいきません。パッと「ら」を調べることができないのです。

スクリーンショット 2020-08-29 12.51.37

そこでコンピューターは「あ」から探し始めます。

1から探し始めるのは線形探索ですね。少ないデータ量の辞書なら、線形探索で良いですが、今回の辞書は膨大な量があることを仮定すると1から探していくととんでもない時間がかかりそうです。

そこで一度辞書を半分に分けます。

スクリーンショット 2020-08-29 12.55.51

すると、「は」「ひ」「ふ」「へ」「ほ」の「ふ」あたりで分けることになるでしょう。

「ふ」を真ん中にしたら、「あ」から数えるより「ふ」から数えた方が「ら」は近いことがわかります。

スクリーンショット 2020-08-29 13.00.26

次にまた、「ふ」で半分に分けた後半の辞書を半分に分けます。
「ふ」から「ん」 を後半とすると、「ゆ」あたりが後半の真ん中にあるとわかります。

スクリーンショット 2020-08-29 12.57.50

「ゆ」を真ん中にしたら、「ふ」から数えるより「ゆ」から数えた方が「ら」は近いことがわかります。

スクリーンショット 2020-08-29 13.00.26

「ゆ」からのデータ量なら線形探索で探すことが簡単です。

簡単な例ですが、データ探索にかかる時間は約1/4になりました。

これが二分探索です。

2分探索をJavaScriptで表してみると以下のようになります。

let array = [1, 5, 10 ,15, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75];

function binary_search(key) {
 let searchLeft = 0;
 let searchRight = array.length - 1;
 let half;

 while (searchLeft < searchRight) {
   half = Math.ceil((searchRight + searchLeft) / 2);
   if (parseInt(key) === array[half]) {
     console.log(`${key}は配列の${half + 1}番目にあります。`);
     break;
   } else if (parseInt(key) < array[half]) {
     searchRight = half;
   } else if (parseInt(key) > array[half]) {
     searchLeft = half;
   } else {
     console.log("なし");
     break;
   }
 }
}

binary_search(15); //15は配列の4番目にあります。
binary_search(75); //75は配列の15番目にあります。
binary_search(76); //なし


今回はここまでとします。

次回はO^2であるソートアルゴリズムについて紹介します。

本日もご精読ありがとうございました。


この記事が参加している募集

習慣にしていること

よろしければサポートお願いします! サポートは、サービスの開発・改良や、記事を書く際の素材費とさせていただきます。 少しでも有益な情報発信をしていけるよう努めてまいります。 是非とも応援よろしくお願いします!!!🙇‍♂️