12.3.1 Finding the Maximum of an Array

Suppose that we have an array T[1..N] of N integers. Let X be the problem of finding the index of the largest element of the array. Suppose further that we are constrained to use comparisons of the form T[i]<T[j] as the only kind of value-testing allowed.

The "obvious" algorithm to solve X is:


int function maxIndex(T[1..N]) 
{    
  maxLocation = 1;    
  for (position=2; position<= N; position++)      
      if    (T[position] > T[maxLocation])
      then  maxLocation = position  ;
  return maxLocation ;
}
We can use an adversary argument to prove that no comparison-based algorithm can solve problem B without performing at least N-1 comparisons.

We can't get this information from a decision tree analysis: if we imagine that a comparison-based algorithm Al has been transformed into a decision tree, then we can observe that the tree has at least N leaves (there are N possible indices at which the max value could be found). Section 12.2 of these notes contains a proof that a binary tree with N nodes has height H>=lg(N). Therefore the number of comparisons required by Al is at least lg(N). That is a lower bound on the complexity of problem X, but it is a very low lower bound.

Here is an adversary argument that provides a sharper bound:

Suppose Al is an algorithm that finds the index of the max.

Every time that Al does a comparison, the "daemon" answers in a manner consistent with the hypothesis that T[i]=i for all i. In other words, when Al asks "Is T[i]<T[j]?", the daemon answers "yes" if i<j, and "no" otherwise.

(Note that the question "Is T[i]<=T[j]?" is equivalent to "Is T[j]<T[i]?" The answer to the first question is "yes" if and only if the answer to the second is "no". Therefore we can assume that all of Al's comparisons are of the form: "Is T[i]<T[j]?")

The daemon also keeps track of the set of indices r for which the daemon has said that T[r]<T[j] for some index j. In other words the set of "losers" is initialized to the empty set, and each time the daemon says "yes" to a question of the form "Is T[i]<T[j]?", it also places i into the set of "losers".

If an index p is not among the losers, it means that the daemon has never stated that T[p]<T[j] -- not for any value of j. From Al's point of view, this means that it could be true that T[p]>=T[j] for every index j. Thus, Al has not been able to rule out the possibility that T[p] is the max value of the array.

If Al stops before making N-1 comparisons, then "losers" contains less than N-1 elements. Therefore there are still at least two array elements T[p] and T[q] that, for all Al knows, could be the max.

If Al stops after doing less than N- 1 comparisons and claims that k is the index of the max, the daemon can choose one of the non-loser indices p or q that is not equal to k (say it's p for definiteness), and claim that T[i]=i for all values of i except that T[p]=N+1. Every answer that the daemon has made has been consistent with that hypothesis -- it could have been so. Therefore, if Al is a correct algorithm, it will not stop before making at least N-1 comparisons.