アルゴリズムがO(log n)であるかどうかの判別


25

CS理論を更新し、アルゴリズムO(log n)の複雑さを識別する方法を知りたいです。具体的には、それを識別する簡単な方法はありますか?

私はO(n)を知っています、あなたは通常単一のループを持っています。O(n ^ 2)は二重ループです。O(n ^ 3)はトリプルループなどです。O(log n)はどうですか。



ああ、それは私が見ていない1つの場所です:)
Atif

回答:


32

私はO(n)を知っています、あなたは通常単一のループを持っています。O(n ^ 2)は二重ループです。O(n ^ 3)はトリプルループなどです。O(log n)はどうですか。

あなたは本当にここで間違った方法で行っています。どのbig-O式が特定のアルゴリズム構造に適合するかを記憶しようとしていますが、実際にアルゴリズムが必要とする操作の数をカウントアップし、それを入力のサイズと比較する必要があります。入力全体をループするアルゴリズムは、単一のループではなく、ループをn回実行するため、O(n)パフォーマンスを備えています。O(log n)パフォーマンスの単一ループを次に示します。

for (i = 0; i < log2(input.count); i++) {
    doSomething(...);
}

したがって、必要な操作の数が入力サイズの対数のオーダーであるアルゴリズムはO(log n)です。big-O分析が示す重要なことは、アルゴリズムの実行時間が入力のサイズに対してどのように変化するかです:入力のサイズを2倍にすると、アルゴリズムはさらに1ステップ(O(log n))かかります、2倍のステップ(O(n))、4倍のステップ(O(n ^ 2))など。

入力を繰り返しパーティション化するアルゴリズムは、通常、パフォーマンスのコンポーネントとして「log n」を持っていることを経験から知るのに役立ちますか?はい。しかし、パーティションを探して、アルゴリズムのパフォーマンスがO(log n)であるという結論にジャンプしないでください。O(n log n)のようなものかもしれません。


3
「サイズの対数のオーダーで」と言うより口語的な方法は、「サイズの桁数のオーダーで」と言うことであることに注意してください。

@Caleb対数の実際の底は、スケーリングについて話すときは重要ではありません。

@Calebが絶対的なことを話すのは、big-Oでは意味がありません。あなたが好むかもしれない言葉遣い:桁数が2倍になると、ステップ数が2倍になります。

@Calebが絶対的なことを話すのは、big-Oでは意味がありません。あなたが好むかもしれない言葉遣い:桁数が2倍になると、ステップ数が2倍になります。

@ThorbjørnRavnAndersenはい、それは「サイズの対数」の意味です。フレーズの問題が何であるかはわかりませんが、別の言い方をすることを選択した場合を除きます。基本的に、私たちは同意すると思います。
カレブ

25

アルゴリズムはO(log n)、構造を1 x 1でスクロールする代わりに、構造を何度も何度も分割し、分割ごとに一定数の操作を行う場合のアルゴリズムです。回答スペースが分割され続ける検索アルゴリズムはO(log n)です。この例はバイナリ検索です。ここでは、番号が見つかるまで順序付けられた配列を何度も何度も分割し続けます。

注:必ずしも半分に分割する必要はありません。


1
入力を2つに分割してから、残りを2 ^(n / 2)回繰り返してから再度分割するとどうなりますか?(もちろん、そのときのことは知っていますが、この単純なアプローチが失敗する例を示したかっただけです)。
タマスシェレイ

@afishそれはちょっと珍しいです。検索するときはめったにありません。
ドナルドフェローズ

1
@DonalFellowsアルゴリズム理論は経験科学ではありません。そして、質問は検索に関するものではなくlog n、人々のトリガーされたバイナリ検索反射について言及しているだけです。
タマスシェレイ

2
パーティショニングは、アルゴリズムをO(log n)にせず、(通常)log nの係数をbig-O制限に追加します。heapsortやmergesortのような再帰ソートは完璧な例です。入力を分割しますが、結果のパーティションの両方を再帰的に分割します。その結果、O(n log n)のパフォーマンスが得られます。
カレブ

@afish:良い点。この答えの私の目標は、質問の性質を考えて、できるだけシンプルに保つことです。この構造を単純に理解するために、「構造を半分に分割する...」という行を「構造を半分に分割する...各分割に対して一定数の操作を行う」に変更しました。
ケーシーパットン

2

典型的な例は、バイナリ検索を扱うものです。たとえば、バイナリ検索アルゴリズムは通常O(log n)です。

バイナリ検索ツリーがある場合、検索、挿入、削除はすべてO(log n)複雑です。

スペースを継続的にパーティション分割する状況には、多くの場合、log nコンポーネントが関係します。多くのソートアルゴリズムがO(nlog n)複雑になるのは、このためです。多くの場合、セットを分割し、進行するにつれてソートするからです。


1

「シングルループ-> O(n)、ダブルループ-> O(n ^ 2)」のように単純にしたい場合、答えはおそらく「ツリー-> O(log n)」です。ツリーをルートから1つ(すべてではない!)のリーフに、またはその逆に、より正確にトラバースします。ただし、これらはすべて単純化しすぎです。


だから、私の答えの何が問題になっていますか?私は建設的な批判を受け入れています。
スカーフリッジ

0

アルゴリズムがO(log N)であるかどうかを識別する簡単な方法があるかどうかを知りたい。

さて、実行して時間を計ってください。入力1.000、10.000、100.000および100万に対して実行します。

実行時間が3,4,5,6秒(または数倍)のように見える場合は、O(log N)と安全に言うことができます。それがより多くの場合:1,10,100,1000秒なら、おそらくO(N)です。そして、3,40,500,6000秒のような場合、O(N log N)です。


誰もが明白な理由のために:-)この回答に1 upvoteと1 downvote、両方を与える必要があります
gnasher729
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.