最高の2つの数字を見つける-コンピューターサイエンス
-
22-07-2019 - |
質問
私は、数字のリストから上位2つの数字を見つけるアルゴリズムを見つけようとしています。
バブルソートまたはそれらの行に沿った何かの最初のステップを実行することにより、最大数はn-1段階で見つけることができます。私にとっては、平均で合計1.5n回の比較で、次に高い数値を見つけることもできるようです。
私の教授は、n + log(n)の比較で最高の2つの数値を見つけるためのアルゴリズムを書くように宿題を設定しました。これも可能ですか?アイデア、提案はありますか?
編集:n + log(n)と言うとき、O(n + log n)ではなく、正確にn + log nを参照しています
解決
はい、(n + log n)以下でそれを行うことができます。答えを出さずにはどうすればいいか本当にわかりませんが、試してみましょう。 :-)
n個の数字を取得し、それらを一度にペアで比較します。 ceil(n / 2)の「勝者」を選び、「バイナリツリーのように」繰り返します。質問:最大のものを見つけるのに何回の比較が必要ですか?これを「勝者」とする人の数勝つ? 2番目に大きい人は誰を失ったでしょうか?では、2番目に大きい数を見つけるのに、今では何回の比較が必要ですか?
答えは、合計が n-1 + ceiling(log n)-1 の比較であることが判明しました。ここで、ログは2を底としています。最悪の場合、これよりうまくやることはできません。
他のヒント
編集:おっと、愚かさのために単純なものを見逃した。この解決策は正しくありませんが、まだavg(n + log(n))であるため、ここで保持しています。私の愚かさを指摘してくれたShreevatsaRに感謝します。私はツリー検索を検討しましたが、log(n)で2番目に大きい数を見つけるためのバックトラックのアイデアを完全に見落としました。
とにかく、ここで、劣等アルゴリズムがavg(n + log(n))を超えない理由についての私の証明に従います。実際には、少なくともかなりのパフォーマンスを発揮するはずです。
- 最初に、2番目に記録された数と比較します。
- その比較が成功した場合にのみ、記録された最大数と比較します。
平均n + log nであることを証明するには、最初の比較が平均log(n)回だけ成功することを証明する必要があります。そして、それは見たり実証したりするのはかなり簡単です。
- リストのソートされたバージョンで現在の2番目に大きい数の実際の位置としてPを想定し、アルゴリズムを実行します
- P> 2の場合、より大きな数が見つかった場合、新しいPは平均でP / 2以下になります。
- P = 2の場合、現在の2番目に大きい数よりも大きい数がないため、最初の比較は成功しません。
- Pは最大でNに等しい
- 2、3、4から、最初の比較が平均してlog(N)回以上成功しないことを確認するのは簡単です。
これについてはどうですか:
for each listOfNumbers as number
if number > secondHighest
if number > highest
secondHighest = highest
highest = number
else
secondHighest = number
ShreevatsaRが投稿した回答はO(n log n)のようです。
最初のパス(n回の操作)では、n / 2個の回答が生成されます。繰り返しますが、n / 4の答えを生成するためにn / 2の操作を行うことを意味すると思います。ループログをn回実行します。これは、マージソートが毎回nノードを常に処理することを除いて、マージソートによく似ています。また、ループログをn回実行します。また、このアルゴリズムが2番目の最大数を追跡する方法がわかりません。
nickfには正しい答えがあります。最悪の場合は、リストが並べ替えられたときに2n回の比較が行われます。つまり、O(n)です。
btw、O(n + log n)はO(n)です。順序表記は、最悪の場合の漸近的成長を示します。
カウントソート、基数ソート、バケットソート、またはその他の線形時間アルゴリズムを使用して、リストを降順で最初にソートできます。次に、ソートされたリストの最初の2つの要素を取得します。 したがって、これには(n)+ 2 =(n)が必要です
各アルゴリズムには独自の仮定があるため、このアルゴリズムは線形時間でソートできることに注意してください。
擬似コード(これは本質的にnではないのですか?)
int highestNum = 0
int secondHighest = highestNum
for(i = 0; i < list.length; i++)
{
if(list[i] >= highestNum)
{
secondHighest = highestNum
highestNum = list[i]
}
}