我正在试图找出一种算法来查找数字列表中最高的2个数字。
最高的数字可以在n-1阶段找到,也许是通过冒泡排序的第一步或沿着这些线的东西。对我而言,似乎找到次高的数字也可以在平均总共1.5n的比较中找到。
我的教授给我们做了一个功课,写了一个在n + log(n)比较中找到最高2个数字的算法。这甚至可能吗?有什么想法,建议吗?
编辑:当我说n + log(n)时,我不是指O(n + log n),而是指n + log n
答案 0 :(得分:6)
是的,可以在不超过(n + log n)的情况下完成。我真的不能告诉你如何不给出答案,但让我试试。 :-)
取n个数字,一次比较它们。取ceil(n / 2)“获胜者”,并重复,“就像一棵二叉树”。问题:找到最大的一个比较需要多少次比较?这个“胜利者”赢了多少人?第二大人可能输给谁?那么现在需要多少次比较来找到第二大数字?
答案结果是总共 n-1 + ceiling(log n) - 1 比较,其中日志是基数2.您还可以使用对抗性论证来证明它在最糟糕的情况下,不可能比这更好。
答案 1 :(得分:2)
编辑:哎呀,由于愚蠢而错过了一件简单的事情。这个解决方案不正确,虽然我把它保留在这里因为它仍然是avg(n + log(n))。感谢ShreevatsaR指出我的愚蠢。我确实考虑了树搜索,但完全错过了回溯的想法,以找到log(n)中第二高的数字。
无论如何,这里遵循我的证据,为什么劣等算法不超过avg(n + log(n))。在现实生活中,它至少应该表现得相当不错。
为了证明它平均为n + log n,我们只需要证明第一次比较平均只能成为log(n)次。这很容易看到或证明。
答案 2 :(得分:0)
这个怎么样:
for each listOfNumbers as number
if number > secondHighest
if number > highest
secondHighest = highest
highest = number
else
secondHighest = number
答案 3 :(得分:0)
ShreevatsaR发布的答案似乎是O(n log n)。
第一遍(n次操作)产生n / 2个答案。通过重复,我猜你的意思是你将进行n / 2次操作以产生n / 4个答案。你将经历n次循环日志。这很像合并排序,但合并排序总是每次处理n个节点。它还运行循环日志n次。我不知道这个算法将如何跟踪第二个最高数字。
nickf有正确的答案。最坏的情况是当列表被排序时,它将进行2n次比较 - 即O(n)。
btw,O(n + log n)是O(n),顺序符号是指最坏情况下的渐近增长。
答案 4 :(得分:0)
您可以使用计数排序,基数排序,桶排序或其他线性时间算法来按降序排列列表。然后只需获取排序列表的前2个元素。 所以这将采用(n)+ 2 =(n)
请注意,此算法可以按线性时间排序,因为每个算法都有自己的假设。
答案 5 :(得分:0)
伪代码(这不是基本上是n?)
int highestNum = 0
int secondHighest = highestNum
for(i = 0; i < list.length; i++)
{
if(list[i] >= highestNum)
{
secondHighest = highestNum
highestNum = list[i]
}
}