二分探索の複雑さを計算する方法


144

誰かが二分探索は探索に必要な入力を半分にするので、それがlog(n)アルゴリズムであると誰かが言うのを聞いた。私は数学の出身ではないので、それを理解することはできません。誰かがもう少し詳しく説明できますか?対数系列で何かしなければならないのですか?


1
これはあなたを助けるかもしれません:stackoverflow.com/a/13093274/550393
2cupsOfTech

回答:


385

実際には複雑ではありませんが、これをより数学的な方法で確認します。IMOは非公式のものとしてより明確です:

問題は、1になるまでNを2で割ることができる回数です。これは本質的に言って、あなたがそれを見つけるまで二分探索(要素の半分)をしてください。数式では、これは次のようになります。

1 = N / 2 x

2 xを掛ける:

2 x = N

ログ2を実行します。

log 2(2 x)= log 2 N
x * log 2(2)= log 2 N
x * 1 = log 2 N

これは、すべてを分割するまでログをN回分割できることを意味します。つまり、要素が見つかるまでログNを分割する(「バイナリ検索ステップを実行する」)必要があります。


t(n)=(2 ^ 2)* Kと計算しました。ログ形式にする方法は?
シャンカーン

1
同じ概念をグラフィカルに説明:stackoverflow.com/a/13093274/550393
2cupsOfTech

私が欠けている部分は、7つのエントリを持つBSTがある場合、その式は何ですか?log2(7)?私はすべての可能な結果を​​用いて力ずくの計算を行い、log2(7)と等しくない答えを見つけたので、私は何を間違っているのですか?
ペリーモンシャウ2016年

1
二分木の説明よりもずっと簡単です。
はNoName

1
非常に良い答え
VHS

22

二分探索の場合、T(N)= T(N / 2)+ O(1)//反復関係

再帰関係の実行時の複雑さを計算するためにマスター定理を適用する:T(N)= aT(N / b)+ f(N)

ここで、a = 1、b = 2 => log(a base b)= 1

また、ここでf(N)= n ^ c log ^ k(n)// k = 0&c = log(a底b)

したがって、T(N)= O(N ^ c log ^(k + 1)N)= O(log(N))

出典:http : //en.wikipedia.org/wiki/Master_theorem


1
なぜa = 1でb = 2のときにlog(a base b)が1なのですか?
GAURANG VYAS 2017

16

T(n)= T(n / 2)+1

T(n / 2)= T(n / 4)+ 1 + 1

T(n)= T(n / 4)+ 1 + 1になるように、The(n / 2)の値を上に入れます。。。。T(n / 2 ^ k)+ 1 + 1 + 1 ..... + 1

= T(2 ^ k / 2 ^ k)+ 1 + 1 .... + 1 kまで

= T(1)+ k

2 ^ k = nをとったので

K = log n

したがって、時間の複雑さはO(log n)です。


10

検索時間の半分ではないため、log(n)にはなりません。対数的に減少します。これについて少し考えてみましょう。テーブルに128のエントリがあり、直線的に値を検索する必要がある場合、値を見つけるには平均で約64のエントリが必要になります。それはn / 2または線形時間です。バイナリ検索を使用すると、反復ごとに可能なエントリの1/2を排除するため、最大7回の比較で値を見つけることができます(128の対数2は7または2の7乗は128です)。これはバイナリサーチの力。


ネクロポストでは申し訳ありませんが、128は均等に塗りつぶされたツリーではありません。基本的な例を使用してこれを理解しましたが、7つのエントリがツリーを3つのレイヤーで均等に埋めていることがわかりました。複雑さは17/7(比較の合計の平均)であると計算しました。これは2.43です。しかし、log2(7)は2.81です。だから私はここで何が欠けていますか?
ペリーモンシャウ

2つの答え-最初の答えはここにあります。数学にエラーがなくても、線形の平均の2.43よりも2.43の平均の方が優れており、これは低い値です。数百のエントリに入ると、log2()は線形よりもはるかに優れています。私はあなたがこれを見ると思うので、次へ。
Michael Dorgan

1
2番目の回答:7にすべてが入力されている場所に、どのようなツリーがあるかわかりません。8エントリの完全なツリーについて考えると、合計8葉の3レベルの深いツリーが表示されます。このツリーでは、検索する数に関係なく、ルートからリーフに至るまでに合計3回の比較が必要です。7つのエントリの場合、パスの1つで比較が1つ少なくなるため、20/7(6つのノードで3つの比較、1つのノードで2つの比較)となり、〜2.85になります。Log2(7)は〜2.81です。.04の違いを説明するための数学の背景はありませんが、小数ビットが利用できないことやその他の魔法がないことに関係していると思います:
Michael Dorgan

数は葉の数です!?ノードの数ではありませんか?さて、それは私が見逃していた大きな情報でした。各分岐ノードも潜在的な停止点であるときに、関数が葉に基づいているのは奇妙に思えます。とにかく、私のためにそれを正してくれてありがとう!
ペリーモンシャウ

5

二分探索アルゴリズムの時間の複雑さは、O(log n)クラスに属します。これは、ビッグO表記と呼ばれます。これを解釈する方法は、サイズnの入力セットが与えられた場合、関数の実行にかかる時間の漸近的な増加はを超えないことlog nです。

これは、ステートメントなどを証明できるようにするための正式な数学的用語です。非常に簡単な説明があります。nが非常に大きくなると、log n関数は、関数の実行にかかる時間より長くなります。「入力セット」のサイズnは、リストの長さです。

簡単に言うと、バイナリ検索がO(log n)にあるのは、反復ごとに入力セットが半分になるためです。逆の状況で考える方が簡単です。x回の反復で、バイナリ検索アルゴリズムが最大でリストをどのくらい長く検査できるか?答えは2 ^ xです。このことから、逆は、長さnのリストに対して、バイナリ検索アルゴリズムが平均してlog2 n回の反復を必要とすることがわかります。

なぜO(log n)であり、O(log2 n)ではないのかというと、単純に言えば、大きなO表記定数を使用しても意味がありません。


4

ここにウィキペディアのエントリがあります

単純な反復アプローチを見てください。必要な要素が見つかるまで、検索する要素の半分を削除するだけです。

ここでは、数式を作成する方法について説明します。

最初にN個の要素があるとします。次に、最初の試みとして「N / 2」を実行します。ここで、Nは下限と上限の合計です。Nの最初の値は(L + H)に等しくなります。Lは検索するリストの最初のインデックス(0)で、Hは最後のインデックスです。運が良ければ、見つけようとする要素は真ん中になるでしょう[eg。リスト{16、17、18、19、20}で18を検索し、⌊(0 + 4)/2⌋= 2を計算します。ここで0は下限です(L-配列の最初の要素のインデックス) 4は上限です(H-配列の最後の要素のインデックス)。上記の場合、L = 0およびH = 4です。ここで、2は、検索している要素18のインデックスです。ビンゴ!あなたは見つけた。

ケースが別の配列{15,16,17,18,19}であったが、まだ18を検索していた場合、幸運ではなく、最初のN / 2(which(0 + 4)/)を実行することになります。 2⌋= 2であり、インデックス2の要素17が探している数ではないことを理解します。次の反復的な方法で、配列の少なくとも半分を探す必要がないことがわかります。したがって、基本的には、以前の検索で見つけられなかった要素を見つけようとするたびに、以前に検索した要素のリストの半分を検索することはありません。

だから最悪のケースは

[N] / 2 + [(N / 2)] / 2 + [((N / 2)/ 2)] / 2 .....
つまり、
N / 2 1 + N / 2 2 + N / 2 3 + ..... + N / 2 x …..

…検索が終了するまで、検索しようとしている要素がリストの最後にあります。

これは、 xが2 x = NであるようなN / 2 xに到達したときが最悪のケースであることを示しています。

他のケースでは、N / 2 xです。 ここで、xは2 x <Nのようなものです。xの最小値は1になる可能性があり、これが最良のケースです。

数学的に最悪の場合は
2 x = N
=> log 2(2 x)= log 2(N)
=> x * log 2(2)= log 2(N)
=> x * 1 = log 2(N)
=>より正式⌊log 2(N)+1⌋


1
より正式なバージョンをどのくらい正確に入手しますか?
カレ

床関数が使用されます。詳細は、回答で提供されているwikiリンク(en.wikipedia.org/wiki/Binary_search_algorithm)のパフォーマンスセクションにあります。
RajKon、


2

Binary Searchの反復がk回の反復後に終了するとします。各反復で、配列は半分に分割されます。したがって、任意の反復での配列の長さがnであるとします。反復1では

Length of array = n

イテレーション2では

Length of array = n⁄2

イテレーション3では

Length of array = (n⁄2)⁄2 = n⁄22

したがって、反復kの後、

Length of array = n⁄2k

また、我々は、k個の分割後の後、ことを知っている配列の長さは1となる ため

Length of array = n⁄2k = 1
=> n = 2k

両側にログ機能を適用する:

=> log2 (n) = log2 (2k)
=> log2 (n) = k log2 (2)
As (loga (a) = 1)

したがって、

As (loga (a) = 1)
k = log2 (n)

したがって、バイナリ検索の時間の複雑さは

log2 (n)

1

二分探索は、このような問題を繰り返し半分に分割することで機能します(詳細は省略)。

[4,1,3,8,5]で3を探す例

  1. アイテムのリストを注文する[1,3,4,5,8]
  2. 真ん中のアイテム(4)を見て、
    • それがあなたが探しているものなら、止めて
    • 大きい場合は前半を見てください
    • 少ない場合は後半を見て
  3. 新しいリスト[1、3]でステップ2を繰り返し、3を見つけて停止します

問題を2つに分割すると、2項検索になります。

検索では、正しい値を見つけるためにlog2(n)ステップのみが必要です。

アルゴリズムの複雑さについて学びたい場合は、アルゴリズム入門をお勧めします。


1

リストを毎回半分に減らすので、リストを2で除算するときに1を取得するステップの数を知る必要があるだけです。以下の与えられた計算では、xは1つの要素を取得するまでにリストを分割する回数を示します(最悪の場合)。

1 = N / 2x

2x = N

log2を取る

log2(2x)= log2(N)

x * log2(2)= log2(N)

x = log2(N)


1

T(N)= T(N / 2)+ 1

T(N)= T(N / 2)+ 1 =(T(N / 4)+ 1)+ 1

...

T(N)= T(N / N)+(1 + 1 + 1 + ... + 1)= 1 + logN(2を底とする対数)= 1 + logN

したがって、バイナリ検索の時間の複雑さはO(logN)です。


0
ok see this
for(i=0;i<n;n=n/2)
{
i++;
}
1. Suppose at i=k the loop terminate. i.e. the loop execute k times.

2. at each iteration n is divided by half.

2.a n=n/2                   .... AT I=1
2.b n=(n/2)/2=n/(2^2)
2.c n=((n/2)/2)/2=n/(2^3)....... aT I=3
2.d n=(((n/2)/2)/2)/2=n/(2^4)

So at i=k , n=1 which is obtain by dividing n  2^k times
n=2^k
1=n/2^k 
k=log(N)  //base 2

0

皆さんのために、例を挙げて簡単にします。

簡単にするために、配列に32の要素がソートされた順序であり、そこからバイナリ検索を使用して要素を検索するとします。

1 2 3 4 5 6 ... 32

32を検索するとします。最初の反復の後、

17 18 19 20 .... 32

2回目の繰り返しの後、

25 26 27 28 .... 32

3回目の繰り返しの後、

29 30 31 32

4回目の繰り返しの後、

31 32

5回目の反復では、値32が見つかります。

これを数式に変換すると、

(32 X(1/2 5))= 1

=> n X(2 -k)= 1

=>(2 k)= n

=> k log 2 2 = log 2 n

=> k = log 2 n

したがって、証拠。


0

これは、可読LaTeXを使用した、マスター定理を使用したソリューションです。

二分探索の再帰関係の各再帰について、ランタイムT(N / 2)で問題を1つのサブ問題に変換します。したがって:

T(n)= T(n / 2)+1

マスター定理に代入すると、次のようになります。

T(n)= aT(n / b)+ f(n)

ここで、Logbais 0でf(n)が1であるため、マスター定理の2番目のケースを使用できます。

f(n)= O(1)= O(n0)= O(nlogba)

この意味は:

T(n)= O(nlogbalogn)= O(n0logn)= O(logn)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.