O(log n)時間でソートされていない配列の最大値を見つけるアルゴリズムは存在しますか?
この質問はよく聞かれ(これは人気のあるCSの宿題の質問か何かですか?)、答えは常に同じです:no。
数学的に考えてください。配列がソートされていない限り、log(n)
の動作を与えるために「半分にカット」するものは何もありません。
より詳細な議論については、質問のコメントを読んでください(とにかく質問の範囲から外れている可能性があります)。
これを考慮してください:every要素を訪問せずに、訪問していない要素がこれまでに見つけた最大のものよりも大きくないことをどうやって知ることができますか?
O(log(N))
でこれを行うことはできません。配列内のすべての項目にアクセスして、それが大きいかどうかを判断する必要があるため、最良/最悪/平均の場合はO(N)
です。配列はソートされていないため、角を切ることはできません。
並列化の場合でも、これはO(N)
では実行できません。Big-O表記では、CPUの数や各CPUの頻度は関係ないためです。 。これから抽象化されて、問題の大まかな推定値が得られます。
ジョブの分割に費やされた時間は順次実行の時間と等しいと見なすことができるため、並列化は無視できます。これは、定数が無視される理由によるものです。以下はすべて同じです。
O(N) = O(Const * N) = O(N / Const) = O(N + Const) = O(N - Const)
一方、実際には、分割統治並列アルゴリズムはパフォーマンス上の利点をもたらす可能性があるため、実行速度が少し速くなる可能性があります。幸いなことに、Big-Oは、このきめ細かいアルゴリズムの複雑さの分析を処理しません。
いいえ、O(n)です。最悪の場合、アレイのすべてのメンバーを訪問して比較する必要があります。
番号。少なくとも1回は配列を反復処理する必要があります。
もちろん違います 。他の要素とまだ比較していない要素がまだあるとします。したがって、比較していない要素が最大要素ではないという保証はありません。
比較グラフ(要素の頂点と比較のエッジ)に複数のコンポーネントがあるとします。この場合、エッジを配置する必要があります(最大2つのコンポーネントの間に最適な方法で)。n-1で操作を実行する必要があることがわかります。
これは非常に古いですが、私は与えられた答えに同意しません。 [〜#〜] yes [〜#〜]、並列ハードウェアを使用して、対数時間で実行できます。
時間計算量は次のようになります。
_O(log(n) * log(m))
_
n
は、比較する数値の量です。 m
は各数値のサイズです。
ただし、ハードウェアのサイズは次のようになります。
_O(n * m)
_
アルゴリズムは次のようになります。
ペアで数字を比較します。キャリー先見コンパレータを使用した場合、この時間はO(log(m))
、サイズはO(n * m)
です。
1の結果を使用して、1の両方の入力を多重化します。この時間はO(1)
で、サイズはO(n * m)
です。
これで、初期サイズの半分の配列ができました。手順1に進みます。このループはlog(n)
回繰り返されるため、合計時間はO(log(n) * log(m))
、合計サイズはO(n * m)
です。
さらにいくつかのMUXを追加すると、アルゴリズムの複雑さを増すことなく、必要に応じて最大数のインデックスを追跡することもできます。
セグメントツリーを使用すると役立つと思います。log(N)コストを達成できます。