c++
呼び出される関数があり、std::nth_element
線形時間で配列の n 番目の要素を見つけることができます。この関数を使用すると、N - n
- 番目の要素 (N
は配列内の要素の総数) を見つけて、そこから 1 を引く必要があります。
で解決策を探すときC
、この機能を利用することはできませんが、同様に解決策を実装できます。nth_element
qsort と非常によく似た処理を実行しますが、n 番目の要素がある配列の部分でのみ分割を実行します。
nth_element
ここで、実装したとしましょう。二分探索と を組み合わせたようなものを実行しますnth_element
。まず、質問の答えが配列の中央の要素 (つまり、N/2 番目の要素) であると仮定します。を使用してth 要素nth_element
を見つけます。N/2
それが私たちが知っているよりも多い場合N/2
、あなたの問題に対する答えは少なくともN/2
です。それ以外の場合は、それより少なくなります。いずれにせよ、答えを見つけるために、N/2
th 要素によって作成された 2 つのパーティションのうちの 1 つだけを続行します。このパーティションが正しいもの (要素がよりも大きいN/2
) である場合、同じ問題を解決し続けます。M
N/2
x
x + N/2 > M
. 2 つの部分問題の複雑さは同じです。関心のある間隔が length になるまで、この操作を続けます1
。
上記のアルゴリズムの複雑さが線形であることを証明しましょう。1つ目nth_element
は の順序で線形に操作を実行しN
、2つ目nth_element
は配列の半分のみを考慮しN/2
て 3 つ目の順序で操作を実行します - の順序などN/4
です。全体として、 の順序で操作を実行しますN + N/2 + N/4 + ... + 1
。この合計はそれよりも小さい2 * N
ため、複雑さは依然として線形です。
あなたのソリューションは、複雑さがあるため、上記で提案したものよりも漸近的に遅くなりますが、O(n*log(n))
私のソリューションの複雑さはO(n)
です。