找到第二个最小值

时间:2014-10-13 08:05:49

标签: c++ arrays time-complexity minimum

我想在数组列表中找到第二个最小值。这是我的代码。有更好的方法吗?

int main(){
    int a[5]={7,5,45,89,12};
    int smallest=a[0];
    int index;
    for(int i=0;i<5;i++){
        if(a[i]<smallest){
            smallest=a[i];
            index=i;
        }
    }

    smallest=a[0];
    for(int i=0;i<5;i++){
        cout<<i;
        if((a[i]<smallest )&& (i!=index)){
            smallest=a[i];
        }
    }
    cout<<"second smallest value is: "<<smallest;  

此代码在O(n)时间内运行?对于第一个循环,它需要n个步骤,而对于另一个循环,它也需要n个步骤。因此,它总共需要O(n)时间复杂度。
这是对的吗?如果我错了,有人可以纠正我吗

5 个答案:

答案 0 :(得分:5)

您可以使用STL算法nth_element,复杂度为 O(n)

#include <iostream>
#include <algorithm>

int main(int argc, char** argv) {
    int a[5]={7,5,45,89,12};
    std::nth_element(a, a + 1, a + 5);
    std::cout << "second smallest value is: " << a[1];
    return 0;
}

如果您想保持数组a不变,可以改用partial_sort_copy

int a[5]={7,5,45,89,12}, b[2];
std::partial_sort_copy(a, a + 5, b, b + 2);
std::cout << "second smallest value is: " << b[1];

在这种情况下,复杂性也是 O(n)

答案 1 :(得分:4)

是的,它 O(n),但实际上没有必要两次运行该列表。

您可以通过存储最小和最小的值来完成一次。

例如,请考虑以下伪代码:

smallest = a[0]
second = a[1]
if second < smallest:
    swap second with smallest
for each index 2 thru a.size - 1 inclusive:
    if a[index] < smallest:
        second = smallest
        smallest = a[index]
    else:
        if a[index] < second:
            second = a[index]

这也是 O(n)但它只通过列表一次,而不是两次。最后,second保持第二高的值。

请注意,列表{1, 1, 2}中的第二高值为1。如果您想以不同方式处理重复项,则需要稍作修改。


在Python中使用示例作为概念证明来实现它,显示结果:

a = [1,45,2,96,4,35]
smallest = a[0]
second = a[1]
if second < smallest:
    smallest, second = second, smallest
for index in range (2, len(a)):
    if a[index] < smallest:
        second = smallest
        smallest = a[index]
    else:
        if a[index] < second:
            second = a[index]
print smallest
print second

输出是:

1
2

作为最小和最小的数字。

答案 2 :(得分:1)

你可以用一个循环来处理它:

int smallest = max
int second = max;

for( int i = 0; i < len; ++i){
    if( a[i] <= smallest){ 
        second = smallest;
        smallest = a[i];
    } else if( a[i] < second){
        second = a[i];
    }
}

max应该是可能的最高值。 len数组的长度。

这也将在O(n)时间内运行。

答案 3 :(得分:1)

您可以在循环的一次迭代中执行此操作:

int main(){
    int a[5]={7,5,45,89,12};
    int smallest = a[0]; 
    int smallest2 = a[0];
    for(int i=1;i<5;i++){
        if(a[i]  < smallest2){
            if(a[i]  < smallest){
              smallest=a[i];
            }
            else {
                smallest2 = a[i];
            }
        }
    }
    cout<<smallest << endl;
    cout<<smallest2 << endl;
    return 0;
}

答案 4 :(得分:1)

解决此问题的另一个好方法是使用MINHEAP。

算法:

  1. 从数组中构建一个minheap树。复杂性= O(n)

  2. 现在再次提取根节点(最小)并最小化数组。复杂度= O(logn)

  3. 现在提取根目录上的第二个最小元素。复杂度= O(logn)。

  4. 要找到第k个最小元素,复杂度变为O(n)+ O(klogn)。

  5. 这里因为你需要第二个最小元素,所以复杂度是O(n)+ O(2logn)