How can we find second maximum from array efficiently?

前端 未结 16 1135
Happy的楠姐
Happy的楠姐 2020-12-25 14:39

Is it possible to find the second maximum number from an array of integers by traversing the array only once?

As an example, I have a array of five integers from whi

相关标签:
16条回答
  • 2020-12-25 15:03

    Your original code is okay, you just have to initialize the max and second_max variables. Use the first two elements in the array.

    0 讨论(0)
  • 2020-12-25 15:03
    // 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);
    
    0 讨论(0)
  • 2020-12-25 15:05

    Step 1. Decide on first two numbers.
    Step 2. Loop through remaining numbers.
    Step 3. Maintain latest maximum and second maximum.
    Step 4. When updating second maximum, be aware that you are not making maximum and second maximum equal.

    Tested for sorted input (ascending and descending), random input, input having duplicates, works fine.

    #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;
    }
    
    0 讨论(0)
  • 2020-12-25 15:08

    Quickselect is the way to go with this one. Pseudo code is available at that link so I shall just explain the overall algorithm:

    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
    

    This is quite obviously based on the good old quicksort algorithm.

    Following this algorithm through, always selecting element zero as the pivot every time:

    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
    

    This will leave your array in an undefined order afterwards, it's up to you if that's a problem.

    0 讨论(0)
  • 2020-12-25 15:08

    The upper bound should have be n+log2⁡n−2, but it bigger than O(n) in case of random selection algorithm, but in worst case it much smaller. The solution might be

    1. build a tree like to find the MAX element with n - 1 comparisons

      max(N) / \ max(N/2) max(N/2)

    2. remove the MAX and find the MAX again log2n - 1 comparison

    PS. It uses additional memory, but it faster than random selection algorithm in worst case.

    0 讨论(0)
  • 2020-12-25 15:10

    You need a second test:

     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];
       }
     }
    
    0 讨论(0)
提交回复
热议问题