寻找数组中第二个最小的元素

时间:2015-08-13 22:14:19

标签: arrays algorithm

我试图仅使用n + ceil(lg n) - 2比较来找到n个元素数组中的第二个最小元素。 CLRS中的提示表示要找到最小的元素。

这需要进行n - 1比较,因此我会在进行ceil(lg n) - 1比较时找到第二个最小的,一旦我知道最大的。

有什么想法吗?

谢谢,

bclayman

4 个答案:

答案 0 :(得分:13)

我们说我们已经列出了 1 ... a n ,其中n是2的幂。

首先对元素进行配对,让我们说 1 带有 2 3 带有 4 等等,并相互比较。这样可以进行n/2次比较。

将所有获胜者推进到下一轮,现在只有n/2个元素,并重复相同的过程。这需要进行n/4次比较。

重复上述步骤,直到你只剩下1个元素,最终获胜者。要实现这一目标,您必须进行n/2 + n/4 + ... + 1 = n-1比较。

这很棒,但哪一个可能是第二小?好吧,它必须是你的赢家在前往顶峰的过程中击败的元素之一。有lg n个这样的输家,所以你需要将它们相互比较以找到最小的(需要进一步的lg n - 1比较)。

最小的输家总体上是第二小的。

很容易证明为什么上述方法总能找到第二小的方法:因为它比每个元素都要小但是最终的胜利者,除了对抗冠军之外,它将赢得每一轮。< / p>

如果n不是2的幂,则过程几乎完全相同,除了输入列表将与下一次确切的2次幂一样长,这就是为什么你最终得到ceil(lg n)

答案 1 :(得分:1)

这是JavaScript中的基本实现,但并不确定它在所有情况下都完全尊重您的O()要求。初始数组也会影响比较计数。

var elements = [ 12, 1 , 3, 4, 65, 7, -43, 8, 3, 8, 45, 2 ];
var nCompare = 0;

var smallest = elements[0], smaller = elements[0];
for(var i = 1; i < elements.length; ++i) {

    ++nCompare;
    if(elements[i] < smaller) {
        ++nCompare;
        if(elements[i] < smallest) {
            smaller = smallest;
            smallest = elements[i];
        }
        else
            smaller = elements[i];
    }
}

document.body.innerHTML = '<pre>\n' +
'Elements: [ ' + elements.join(', ') + ' ]\n' +
'# element: ' + elements.length + '\n' +
'\n' +
'Smallest: ' + smallest + '\n' +
'2nd smallest: ' + smaller + '\n' +
'# compare: ' + nCompare +
'</pre>';

答案 2 :(得分:0)

以下是Java中具有O(n)复杂性的解决方案:

public class MainClass {
    public static void main(String[] args) {
        int[] a = { 4, 2, 8, -2, 56, 0 };
        c(a);
    }

    private static void c(int[] a) {
        int s = Integer.MAX_VALUE;
        int ss = Integer.MAX_VALUE;
        for (int i : a) {
            if (i < s) {
                ss = s;
                s = i;
            } else if (i < ss) {
                ss = i;
            }
        }
        System.out.println("smallest : " + s + " second smallest : " + ss);
    }
}

输出:最小:-2秒最小值:0

答案 3 :(得分:-1)

我认为他们不需要进行cel(log n)-1的额外比较,因为它只能在O(n)中完成,即在一次扫描中借助于下面给出的额外变量: -

for(i,0,no_of_elem-1)
{
 if(min>elem[i])
 {
   second_smallest=min;
   min=elem[i];
 }
}

您只需将先前的最小值存储在变量中,因为扫描完所有元素后,这将是您的答案。