我们如何有效地从阵列中找到第二个最大值?

时间:2010-03-06 14:03:13

标签: c++ arrays algorithm

是否可以通过遍历数组一次从整数数组中找到第二个最大数字?

作为一个例子,我有一个包含五个整数的数组,我想从中找到第二个最大数。以下是我在采访中的尝试:

#define MIN -1
int main()
{
    int max=MIN,second_max=MIN;
    int arr[6]={0,1,2,3,4,5};
    for(int i=0;i<5;i++){
        cout<<"::"<<arr[i];
    }
    for(int i=0;i<5;i++){
        if(arr[i]>max){
            second_max=max;
            max=arr[i];          
        }
    }
    cout<<endl<<"Second Max:"<<second_max;
    int i;
    cin>>i;
    return 0;
}

然而,访问者提出了测试用例int arr[6]={5,4,3,2,1,0};,它阻止它第二次进入if状态。 我对面试官说,唯一的方法是解析数组两次(两个for循环)。有人有更好的解决方案吗?

16 个答案:

答案 0 :(得分:28)

您对maxsecond_max-1的初始化存在缺陷。如果数组的值为{-2,-3,-4}

,该怎么办?

你可以做的是取数组的前2个元素(假设数组至少有2个元素),比较它们,将较小的一个分配给second_max,将较大的一个分配给{{1 }}:

max

然后从第3个元素开始比较,并根据需要更新if(arr[0] > arr[1]) { second_max = arr[1]; max = arr[0]; } else { second_max = arr[0]; max = arr[1]; } 和/或max

second_max

答案 1 :(得分:14)

最简单的解决方案是使用std::nth_element

答案 2 :(得分:7)

您需要进行第二次测试:

 for(int i=0;i<5;i++){  
   if(arr[i]>max){  
     second_max=max;  
     max=arr[i];            
   }
   else if (arr[i] > second_max && arr[i] != max){
     second_max = arr[i];
   }
 }

答案 3 :(得分:2)

你在这里:

std::pair<int, int> GetTwoBiggestNumbers(const std::vector<int>& array)
{
    std::pair<int, int> biggest;
    biggest.first = std::max(array[0], array[1]);  // Biggest of the first two.
    biggest.second = std::min(array[0], array[1]); // Smallest of the first two.

    // Continue with the third.
    for(std::vector<int>::const_iterator it = array.begin() + 2;
        it != array.end();
        ++it)
    {
        if(*it > biggest.first)
        {
            biggest.second = biggest.first;
            biggest.first = *it;
        }
        else if(*it > biggest.second)
        {
            biggest.second = *it;
        }
    }

    return biggest;
}

答案 4 :(得分:2)

您的原始代码没问题,您只需初始化max和second_max变量即可。使用数组中的前两个元素。

答案 5 :(得分:1)

Quickselect是使用这个的方法。伪代码在该链接上可用,因此我将解释整个算法:

QuickSelect for kth largest number:
    Select a pivot element
    Split array around pivot
    If (k < new pivot index)
       perform quickselect on left hand sub array
     else if (k > new pivot index)
       perform quickselect on right hand sub array (make sure to offset k by size of lefthand array + 1)
     else
       return pivot

这很明显是基于良好的旧快速排序算法。

遵循此算法,每次始终选择元素零作为轴:

select 4th largest number:
1) array = {1, 3, 2, 7, 11, 0, -4}
partition with 1 as pivot
{0, -4, _1_, 3, 2, 7, 11}
4 > 2 (new pivot index) so...

2) Select 1st (4 - 3) largest number from right sub array
array = {3, 2, 7, 11}
partition with 3 as pivot
{2, _3_, 7, 11}
1 < 2 (new pivot index) so...

3) select 1st largest number from left sub array
array = {2}

4) Done, 4th largest number is 2

这将使你的阵列在未定义的顺序之后,如果这是一个问题,这取决于你。

答案 6 :(得分:1)

步骤1.确定前两个数字 步骤2.循环显示剩余数字。
步骤3.保持最新的最大值和第二个最大值 步骤4.更新第二个最大值时,请注意您没有使最大值和第二个最大值相等。

针对排序输入(升序和降序),随机输入,具有重复项的输入进行测试,工作正常。

#include <iostream>
#define MAX 50
int GetSecondMaximum(int* data, unsigned int size)
{
    int max, secmax;
    // Decide on first two numbers
    if (data[0] > data[1])
    {
        max = data[0];
        secmax = data[1];
    }
    else
    {
        secmax = data[0];
        max = data[1];
    }
    // Loop through remaining numbers
    for (unsigned int i = 2; i < size; ++i)
    {
        if (data[i] > max)
        {
            secmax = max;
            max = data[i];
        }
        else if (data[i] > secmax && data[i] != max/*removes duplicate problem*/)
            secmax = data[i];
    }
    return secmax;
}
int main()
{
    int data[MAX];
    // Fill with random integers
    for (unsigned int i = 0; i < MAX; ++i)
    {
        data[i] = rand() % MAX;
        std::cout << "[" << data[i] << "] "; // Display input
    }
    std::cout << std::endl << std::endl;
    // Find second maximum
    int nSecondMax = GetSecondMaximum(data, MAX);
    // Display output
    std::cout << "Second Maximum = " << nSecondMax << std::endl;
    // Wait for user input
    std::cin.get();
    return 0;
}

答案 7 :(得分:1)

解决这个问题的其他方法是使用元素之间的比较。例如,

a[10] = {1,2,3,4,5,6,7,8,9,10}

比较1,2并说max = 2和second max = 1

现在比较3和4并将它们中的最大值与最大值进行比较。

if element > max
     second max = max
     element = max
else if element > second max
     second max = element

这样做的好处是,您只需两次比较即可消除两个数字。

如果您对此有任何疑问,请告诉我。

答案 8 :(得分:1)

检查此解决方案。

max1 = a[0];
max2 = a[1];

for (i = 1; i < n; i++)
{
    if (max1 < a[i])
    {
        max2 = max1;
        max1 = a[i];
    }

    if (max2 == max1) max2 = a[i + 1];

    if (max2 == a[n])
    {
        printf("All numbers are the same no second max.\n");
        return 0;
    }

    if (max2 < a[i] && max1 != a[i]) max2 = a[i];
}

答案 9 :(得分:0)

这可能有用,

public static int secondLargest(int[] a){
    int max=0;
    int secondMax=0;

    for(int i=0;i<a.length;i++){
        if(a[i]<max){
            if(a[i]>secondMax){
                secondMax=a[i];
            }
            continue;
        }

        if(a[i]>max){
            secondMax=max;
            max=a[i];
        }

    }
    return secondMax;
}

答案 10 :(得分:0)

上限应为n +log2⁡n-2,但在随机选择算法的情况下,它应大于O(n),但在最坏的情况下,它要小得多。解决方案可能是

  1. 构建一个树,就像找到具有n - 1个比较的MAX元素

    MAX(N)    / \ 最大(N / 2)max(N / 2)

  2. 删除MAX并再次找到MAX log2n - 1比较

  3. PS。它使用额外的内存,但在最坏的情况下比随机选择算法更快。

答案 11 :(得分:0)

我们不能按降序排序并从排序数组中取出第二个元素吗?

答案 12 :(得分:0)

下面的内容如何。 make_heap是O(n)所以这是有效的,这是1遍 我们通过利用它必须是父项的堆子项之一来找到第二个max,它具有最大值。

#include <algorithm>
#include <iostream>

int main()
{
    int arr[6]={0,1,2,3,4,5};

    std::make_heap(arr, arr+6);
    std::cout << "First Max: " << arr[0] << '\n';
    std::cout << "Second Max: " << std::max(arr[1], arr[2]) << '\n';
    return 0;
}

答案 13 :(得分:0)

int max,secondMax;
max=secondMax=array[0];
                                                for(int i=0;i<array.length;i++)
    {                                                   if(array[i]>max)                                                    {                                           max=array[i];                                                   }
                                                        if(array[i]>secondMax && array[i]<max)                                                  {
    secondMax=array[i];                                                 }
    }

答案 14 :(得分:0)

#include <iostream>
using namespace std;

int main() {

   int  max = 0;
    int sec_Max = 0;

    int array[] = {81,70,6,78,54,77,7,78};

    int loopcount = sizeof(array)/sizeof(int);

    for(int i = 0 ; i < loopcount ; ++i)
    {

        if(array[i]>max)
        {
            sec_Max = max;
            max = array[i];
        }

        if(array[i] > sec_Max && array[i] < max)
        {
            sec_Max = array[i];
        }
    }

    cout<<"Max:" << max << " Second Max: "<<sec_Max<<endl;

    return 0;
}

答案 15 :(得分:-1)

// Set the first two different numbers as the maximum and second maximum numbers

 int max = array[0];
 int i = 1;
//n is the amount of numbers

 while (array[i] == max && i < n) i++;
 int sec_max = array[i];
 if( max < sec_max ) {
    tmp = sec_max;
    sec_max = max;
    max = tmp;
 }

//find the second maximum number

 for( ; i < n; ++i ) {
   if( array[i] > max ) {
     sec_max = max;
     max = array[i];
   } else if( array[i] > sec_max && array[i] != max ) {
     sec_max = array[i];
   }
 }
 printf("The second maximum number is %d\n", sec_max);