Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to find max. and min. in array using minimum comparisons?

This is a interview question: given an array of integers find the max. and min. using minimum comparisons.

Obviously, I can loop over the array twice and use ~2n comparisons in the worst case but I would like to do better.

like image 519
Michael Avatar asked Nov 24 '12 18:11

Michael


People also ask

How many comparisons are required to find minimum and maximum element from an array of size 200 if we apply divide and conquer algorithm?

If n is a power of 2, the algorithm needs exactly 3n/2–2 comparisons to find min and max.

What is the minimal number of comparisons needed to find the max in an array of n?

In general, to find largest of N elements you need N-1 comparisons.


3 Answers

1. Pick 2 elements(a, b), compare them. (say a > b)
2. Update min by comparing (min, b)
3. Update max by comparing (max, a)

This way you would do 3 comparisons for 2 elements, amounting to 3N/2 total comparisons for N elements.

like image 134
srbhkmr Avatar answered Oct 17 '22 01:10

srbhkmr


Trying to improve on the answer by srbh.kmr. Say we have the sequence:

A = [a1, a2, a3, a4, a5]

Compare a1 & a2 and calculate min12, max12:

if (a1 > a2)
  min12 = a2
  max12 = a1
else
  min12 = a1
  max12 = a2

Similarly calculate min34, max34. Since a5 is alone, keep it as it is...

Now compare min12 & min34 and calculate min14, similarly calculate max14. Finally compare min14 & a5 to calculate min15. Similarly calculate max15.

Altogether it's only 6 comparisons!

This solution can be extended to an array of arbitrary length. Probably can be implemented by a similar approach to merge-sort (break the array in half and calculate min max for each half).

UPDATE: Here's the recursive code in C:

#include <stdio.h>

void minmax (int* a, int i, int j, int* min, int* max) {
  int lmin, lmax, rmin, rmax, mid;
  if (i == j) {
    *min = a[i];
    *max = a[j];
  } else if (j == i + 1) {
    if (a[i] > a[j]) {
      *min = a[j];
      *max = a[i];
    } else {
      *min = a[i];
      *max = a[j];
    }
  } else {
    mid = (i + j) / 2;
    minmax(a, i, mid, &lmin, &lmax);
    minmax(a, mid + 1, j, &rmin, &rmax);
    *min = (lmin > rmin) ? rmin : lmin;
    *max = (lmax > rmax) ? lmax : rmax;
  }
}

void main () {
  int a [] = {3, 4, 2, 6, 8, 1, 9, 12, 15, 11};
  int min, max;
  minmax (a, 0, 9, &min, &max);
  printf ("Min : %d, Max: %d\n", min, max);
}

Now I cannot make out the exact number of comparisons in terms of N (the number of elements in the array). But it's hard to see how one can go below this many comparisons.

UPDATE: We can work out the number of comparisons like below:

At the bottom of this tree of computations, we form pairs of integers from the original array. So we have N / 2 leaf nodes. For each of these leaf nodes we do exactly 1 comparison.

By referring to the properties of a perfect-binary-tree, we have:

leaf nodes (L) = N / 2 // known
total nodes (n) = 2L - 1 = N - 1
internal nodes = n - L = N / 2 - 1

For each internal node we do 2 comparisons. Therefore, we have N - 2 comparisons. Along with the N / 2 comparisons at the leaf nodes, we have (3N / 2) - 2 total comparisons.

So, may be this is the solution srbh.kmr implied in his answer.

like image 15
Asiri Rathnayake Avatar answered Oct 17 '22 01:10

Asiri Rathnayake


A somewhat different approach, which uses integer arithmetic instead of comparisons (which wasn't explicitly prohibited)

for(int i=0;i<N;i++) {
  xmin += x[i]-xmin & x[i]-xmin>>31;
  xmax += x[i]-xmax & xmax-x[i]>>31;
}
like image 5
Anton Knyazyev Avatar answered Oct 17 '22 03:10

Anton Knyazyev