4

I want to find the second minimum in a array list.Here's my code.Is there a better way to do it?

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;  

This code runs in O(n) time? For the first loop it takes n steps, and for the other for loop also it takes n steps.Therefore altogether it takes O(n) time complexity .
Is this right?Can someone correct me if I am wrong please

clarkson
  • 561
  • 2
  • 16
  • 32
  • 3
    Yes, it is O(N), but the constant multiplier is 2 where you should be able to do it in O(N) with a multiplier of 1. That is, you shouldn't need two loops; one should be sufficient. – Jonathan Leffler Oct 13 '14 at 08:07

5 Answers5

7

Yes, it is O(n) but there's really no need to run through the list twice.

You can do it once by storing both the smallest and second smallest values.

For example, consider the following pseudo-code:

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]

This is also O(n) but it only goes through the list once, rather than twice. At the end, second holds the second highest value.

Just keep in mind that the second highest value in the list {1, 1, 2} is 1. If you want to treat duplicates differently to that, it's a slight modification.


Implementing that in Python with a sample as a proof of concept, shows the result:

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

The output of that is:

1
2

as the smallest and second smallest numbers.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • @paxdiablo I think inside else clause there should be a change as `else{ if((a[i]smallest)){ second=a[i]; } }` otherwise for the array int[] a={1,45,2,96,4,35}; second smallest would be 1 – clarkson Oct 14 '14 at 03:54
  • @clarkson, I don't think that's needed, the `else` itself is ensuring number is >= smallest. Smallest and second can be considered an array and are populated correctly before the loop. Then every other number is checked. If it's smaller than the current smallest, you insert it before smallest. Otherwise if it's smaller than the second, you insert it before second. Otherwise you throw it away. I'll add some real Python code with your sample. – paxdiablo Oct 14 '14 at 04:58
  • @paxdiablo My mistake.In the for loop I was going from index 0.Thanks for the answer – clarkson Oct 14 '14 at 05:18
5

You could use STL algorithm nth_element, the complexity is 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;
}

If you want to keep the array a unchanged, you could use partial_sort_copy instead.

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

in this case, the complexity is O(n) as well.

Jamboree
  • 5,139
  • 2
  • 16
  • 36
1

You can handle it with one loop:

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 should be the highest possible value. len the length of the array.

This will also run in O(n) time.

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
Steffen
  • 2,381
  • 4
  • 20
  • 33
1

You can do this in one iteration of the loop:

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;
}
Dr. Debasish Jana
  • 6,980
  • 4
  • 30
  • 69
  • For the array int[] a={1,45,2,96,4,35} this code doesn't work right?because then first if statement won't get executed and second would get assigned 1 in the first time,and as it is the smallest that would be the end result – clarkson Oct 14 '14 at 04:15
1

Another nice way to solve this problem is using a MINHEAP.

Algorithm:

  1. Build a minheap tree out of your array. Complexity = O(n)

  2. Now extract the root node (smallest) and Min-heapify the array again. Complexity = O(logn)

  3. Now extract the second least element that is on the root. Complexity = O(logn).

  4. To find kth smallest element, the complexity becomes O(n) + O(klogn).

Here since you need 2nd smallest element, the complexity is O(n) + O(2logn)

Gopichand
  • 1,006
  • 1
  • 9
  • 12