找到第二个最小值

finding the second minimum

本文关键字:最小值 第二个      更新时间:2023-10-16

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

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步,对于另一个For循环,它也需要n步。因此,总共需要O(n)的时间复杂性
这是对的吗?如果我错了,有人能纠正我吗?

是的,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

作为最小和第二小的数字。

您可以使用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)

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

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)时间内运行。

您可以在循环的一次迭代中做到这一点:

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;
}

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

算法:

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

  2. 现在提取根节点(最小),然后Min再次堆化数组。复杂性=O(logn)

  3. 现在提取根上倒数第二少的元素。复杂性=O(logn)。

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

这里,由于您需要第二小元素,因此复杂性为O(n)+O(2logn)