找到N个中最大和第二大的数字

时间:2011-04-17 03:00:09

标签: algorithm sorting comparison performance runtime

给定n个数字,我如何找到最多使用n + log(n)比较的最大和第二大数字?

请注意,它不是O(n + log(n)),而是n + log(n)比较。

2 个答案:

答案 0 :(得分:11)

帕夫顿发表评论。

让我详细说明。

正如帕伊顿所说,这可以通过比赛选择来完成。

将此视为一场淘汰单打网球锦标赛,其中球员的能力有严格的顺序,而比赛的结果完全取决于该顺序。

在第一轮比赛中,一半人被淘汰出局。在下一轮另一半等(可能有一些脚本)。

最终赢家将在最后一轮和最后一轮决定。

这可以看作是一棵树。

树的每个节点都将成为该节点子节点之间匹配的赢家。

树叶是球员。第一轮的胜利者是叶子的父母等。

这是n个节点上的完整二叉树。

现在按照胜利者的路径行事。赢家已经进行了log n匹配。现在考虑那些log n匹配的输家。其中第二好的必须是最好的。

获胜者以n-1场比赛决定(你每场比赛淘汰一场),而logn中的获胜者将以logn -1比赛决定。

因此,你可以决定n + logn中最大和第二大的比较。

事实上,它可以证明这是最佳的。在最坏情况下的任何比较方案中,获胜者必须参加登录比赛。

为了证明假设一个点系统,在一场比赛之后,获胜者获得了输家的分数。最初都是从每个1点开始。

最后的胜利者有n分。

现在给出任何算法,它可以安排,以便有更多积分的玩家永远是赢家。由于任何人的得分在该场景中的任何比赛中最多为两倍,因此在最坏的情况下至少需要获胜者所玩的log n匹配。

答案 1 :(得分:1)

这有问题吗?最多3n次比较(不计算i < n比较)。如果算上这个,那就是4n(或者在第二个例子中是5n)。

double first = -1e300, second = -1e300;
for (i = 0; i < n; i++){
  if (a[i] > first){
    second = first;
    first = a[i];
  }
  else if (a[i] > second && a[i] < first){
    second = a[i];
  }
}

另一种编码方式:

for (i = 0; i < n; i++) if (a[i] > first) first = a[i];
for (i = 0; i < n; i++) if (a[i] < first && a[i] > second) second = a[i];