Divide and Conquer PDF
Divide and Conquer PDF
Whatever man prays for, he prays for a miracle. Every prayer reduces itself
to this~Great God, grant that twice two be not four.
-Ivan Turgenev {1818-1883), Russian novelist and short-story writer
123
124 Divide-and-Conquer
problem of size n
subproblem 1 subproblem 2
of size n/2 of size n/2
solution to solution to
subproblem 1 subproblem 2
solution to
the original problem
(which follows), and common sense (we do not compute sums this way, do we?)
all lead to a negative answer to this question.
Thus, not every divide-and-conquer algorithm is necessarily more efficient
than even a brute-force solution. But often our prayers to the Goddess of
Algorithmics-see the chapter's epigraph-are answered, and the time spent on
executing the divide-and-conquer plan turns out to be smaller than solving a prob-
lem by a different method. In fact, the divide-and-conquer approach yields some of
the most important and efficient algorithms in computer science. We discuss a few
classic examples of such algorithms in this chapter. Though we consider only se-
quential algorithms here, it is worth keeping in miud that the divide-and-conquer
technique is ideally suited for parallel computations, in which each subproblem
can be solved simultaneously by its own processor.
As mentioned above, in the most typical case of divide-and-conquer, a prob-
lem's instance of size n is divided into two instances of size n/2. More generally,
an instance of size n can be divided into b instances of size n/b, with a of them
needing to be solved. (Here, a and b are constants; a 2: 1 and b > 1. ). Assuming
4.1 Mergesort 125
that size n is a power of b, to simplify our analysis, we get the following recurrence
for the running time T(n):
where f(n) is a function that accounts for the time spent on dividing the problem
into smaller ones and on combining their solutions. (For the summation example,
a = b = 2 and f (n) = 1.) Recurrence ( 4.1) is called the geneml divide-and-conquer
recurrence. Obviously, the order of growth of its solution T(n) depends on the
values of the constants a and b and the order of growth of the function .f (n). The
efficiency analysis of many divide-and-conquer algorithms is greatly simplified by
the following theorem (see Appendix B).
8(11d) if a< hd
T(11) E 8(11d log n) if a= h"
{
8(n 10g" ") if a > bd
For example, the recurrence equation for the number of additions A (11) made
by the divide-and-conquer sum-computation algorithm (see above) on inputs of
size n = 2k is
A(11) = 2A(nj2) + 1.
Thus, for this example, a= 2, b = 2, and d = 0; hence, since a> bd,
A(11) E 8(n 10g"") = 8(11log2 2 ) = G(n).
Note that we were able to find the solution's efficiency class without going through
the drudgery of solving the recurrence. But, of course, this approach can only es-
tablish a solution's order of growth to within an unknown multiplicative constant,
while solving a recurrence equation with a specific initial condition yields an exact
answer (at least for 11 's that are powers of b).
4.1 Mergesort
Mergesort is a perfect example of a successful application of the divide-and-
conquer technique. It sorts a given array A[O .. n - 1] by dividing it into two halves
A[D .. L11/2J -1] and A[lnf2j .. n -1], sorting each of them recursively, and then
merging the two smaller sorted arrays into a single sorted one.
126 Divide-and-Conquer
The merging of two sorted arrays can be done as follows. Two pointers (array
indices) are initialized to point to the first elements of the arrays being merged.
The elements pointed to are compared, and the smaller of them is added to a new
array being constructed; after that, the index of the smaller element is incremented
to point to its immediate successor in the array it was copied from. This operation
is repeated until one of the two given arrays is exhausted, and then the remaining
elements of the other array are copied to the end of the new array.
8 3 2 9 7 1 5 4
12345789
by one. In the worst case, neither of the two arrays becomes empty before the
other one contains just one element (e.g., smaller elements may come from the
alternating arrays). Therefore, for the worst case, Cmerge(n) = n- 1, and we have
the recurrence
1 ; 1
Cwom(n) = 2Cwm-, 1 (nj2) + n- 1 for 11 > 1,
Hence, according to the Master Theorem, Cwm-,Jn) E 8(11 log n) (why?). In fact,
it is easy to find the exact solution to the worst-case recurrence for n = 2k:
cwa>.>l(n) = 11 logz n- n + 1.
The number of key comparisons made by mergesort in the worst case comes
very close to the theoretical minimum 1 that any general comparison-based sorting
algorithm can have. The principal shortcoming of mergesort is the linear amount
1. As we shall see in Section 11.2, this theoretical minimum is rtog 2 n !l ~ rn log2 n - 1.44n 1.
128 Divide-and-Conquer
of extra storage the algorithm requires. Though merging can be done in place,
the resulting algorithm is quite complicated and, since it has a significantly larger
multiplicative constant, the in-place mergesort is of theoretical interest only.
-----Exercises 4.1 - - - - - - - - - - - - - - - -
1. \;JWrite a pseudocode for a divide-and-conquer algorithm for finding a po-
sition of the l!'.!~~t..~ement in an array of n numbers.
b. What will be your algorithm's output for arrays with several elements of
the largest value?
c. Set up and solve a recurrence relation for the number of key comparisons
made by your algorithm.
d. How does this algorithm compare with the brute-force algorithm for this
problem?
2. a. Write a pseudocode for a divide-and-conquer algorithm for finding values
of both the largest and smallest elements in an array of n numbers.
b. Set up and solve (for n = 2k) a recurrence relation for the number of key
comparisons made by your algorithm.
c. How does this algorithm compare with the brute-force algorithm for this
problem?
3. a. Write a pseudocode for a divide-and-conquer algorithm for the exponen-
tiation problem of computing a" where a > 0 and n is a positive integer.
b. Set up and solve a recurrence relation for the number of multiplications
made by this algorithm.
c. How does this algorithm compare with the brute-force algorithm for this
problem?
4. We mentioned in Chapter 2, that logarithm bases are irrelevant in most
contexts arising in the analysis of an algorithm's efficiency class. Is this true
,
.. for both assertions of the Master Theorem that include logarithms?
5. Find the order of growth for solutions of the following recurrences.
•
a. T(n) = 4T(nf2) + n, T(1) = 1
b. T(n) = 4T(n/2) + n 2 , T(1) = 1
'I
c. T(n) = 4T(nf2) + n 3 , T(l) = 1
6. Apply mergesort to sort the list E, X, A, M, P, L, E in alphabetical order.
7. Is mergesort a stable sorting algorithm?
)S._Ja. Solve the recurrence relation for the number of key comparisons made by
mergesort in the worst case. (You may assume that n = 2k.)
\ \ j\ \\
'\ \ ': \ I.
~
r
4.2 Quicksort 129
it
4.2 Quicksort
Quicksort is another important sorting algorithm that is based on the divide-and-
j I conquer approach. Unlike mergesort, which divides its input's elements according
to their position in the array, quicksort divides them according to their value.
Specifically, it rearranges elements of a given array A(O .. n - 1] to achieve its
partition, a situation where all the elements before some position s are smaller
than or equal to A[s] and all the elements after positions are greater than or equal
toA[s]:
Obviously, after a partition has been achieved, A[s] will be in its final position in
the sorted array, and we can continue sorting the two subarrays of the elements
preceding and following A[s] independently (e.g., by the same method).
ALGORITHM Quicksort(A[Lr])
//Sorts a subarray by quicksort
//Input: A subarray A[Lr] of A[O,n -1], defmed by its left and right indices
II l and r
//Output: Subarray A[l .. r] sorted in nondecreasing order
if l < r
s +-Partition(A[l .. r]) lis is a split position
Quicksort(A[l .. s- 1])
Quicksort(A[s + l..r])
A partition of A[O .. n- 1] and, more generally, ofits subarray A[l .. r] (0::: l <
r ::: n - 1) can be achieved by the following algorithm. First, we select an element
with respect to whose value we are going to divide the subarray. Because of its
guiding role, we call this element the pivot. There are several different strategies
for selecting a pivot; we will return to this issue when we analyze the algorithm's
efficiency. For now, we use the simplest strategy of selecting the subarray's first
element: p = A[l].
There are also several alternative procedures for rearranging elements to
achieve a partition. Here we use an efficient method based on two scans of the
subarray: one is left-to-right and the other right-to-left, each comparing the sub-
array's elements with the pivot. The left-to-right scan, denoted below by index i,
starts with the second element. Since we want elements smaller than the pivot to
be in the first part of the subarray, this scan skips over elements that are smaller
than the pivot and stops on encountering the first element greater than or equal
to the pivot. The right-to-left scan, denoted below by index j, starts with the last
element of the subarray. Since we want elements larger than the pivot to be in
the second part of the sub array, this scan skips over elements that are larger than
the pivot and stops on encountering the first element smaller than or equal to the
pivot.
After both scans stop, three situations may arise, depending on whether or not
the scanning indices have crossed. If scanning indices i and j have not crossed, i.e.,
i < j, we simply exchange A[i] and A[j] and resume the scans by incrementing i
and decrementing j, respectively:
i~
If the scanning indices have crossed over, i.e., i > j, we will have partitioned
the array after exchanging the pivot with A[J]:
Finally, if the scanning indices stop while pointing to the same element, i.e.,
i = j, the value they are pointing to must be equal top (why?). Thus, we have the
array partitioned, with the split positions = i = j:
----i=j--
Ip I all are s p 1- pI all are ~p
We can combine the last case with the case of crossed-over indices (i > j) by
exchanging the pivot with A[J] whenever i 2" j.
Here is a pseudocode implementing this partitioning procedure.
Note that index i can go out of the subarray bounds in this pseudocode. Rather
than checking for this possibility every time index i is incremented, we can append
to array A[O .. n- 1] a "sentinel" that would prevent index i from advancing beyond
position n. The more sophisticated method of pivot selection mentioned at the end
of the section makes such a sentinel unnecessary.
An example of sorting an array by quicksort is given in Figure 4.3.
\
-r
132 Divide-and-Conquer
0 2 3 4 5 6 7
i j
5 3 9 8 2 4 7
i j
5 3 9 8 2 4 7
i j
5 3 4 8 2 9 7
i j
5 3 4 8 2 9 7
i j
5 3 4 2 8 9 7
j
5 3 4 2 8 9 7
2 3 4 5 8 9 7
i j
2 3 4
i
2 3 4
i j
2 1 3 4
j i
2 1 3 4
2 3 4
jj
3 4
j i
3 4
4
i j
8 9 7 (b)
i j
8 7 9
j i
8 7 9
7 8 9
7
9
(a)
FIGURE 4.3 Example of Quicksort operation. (a) The array's transformations with pivots
shown in bold. (b) The tree of recursive calls to Quicksort with input values
1 and r of subarray bounds and split positions of a partition obtained.
According to the Master Theorem, cb"t(n) E 8(n logz n); solving it exactly for
11= 2k yields cb"t(n) = n iogz n.
In the worst case, all the splits will be skewed to the extreme: one of the two
subarrays will be empty, while the size of the other will be just one less than the
size of the subarray being partitioned. This unfortunate situation will happen, in
particular, for increasing arrays, i.e., for inputs for which the problem is already
solved! Indeed, if A[O .. n- 1] is a strictly increasing array and we use A(O] as the
pivot, the left-to-right scan will stop on A[1] while the right-to-left scan will go all
the way to reach A(O], indicating the split at position 0:
j-- ----i
IA[OJI A[lll I A[n-lll
So, after making n + 1 comparisons to get to this partition and exchanging the
pivot A(O] with itself, the algorithm will find itself with the strictly increasing array
A(1 .. n - 1] to sort. This sorting of strictly increasing arrays of diminishing sizes will
continue until the last one A[n- 2 .. n -1] has been processed. The total number
of key comparisons made will be equal to
Cwm·,(n)=(n+1)+n+···+3=
(n + l)(n + 2) -3E8(n ).
2
. 2
Thus, the question about the utility of quicksort comes to its average-case be-
havior. Let Caag(n) be the average number of key comparisons made by quicksort
on a randomly ordered array of size n. Assuming that the partition split can hap-
pen in each positions (0::: s::: n- 1) with the same probability ljn, we get the
following recurrence relation
1 11-1
Caag(n) =- l)(n + 1) + Caag(s) + Cav8 (n -1- s)] for n> 1,
n s=O
Ca, 8 (0) = 0, Caag(1) = 0.
Though solving this recurrence is easier tban one might expect, it is still much
trickier than the worst- and best-case analyses, and we willleave it for the exercises.
Its solution turns out to be
Thus, on the average, quicksort makes only 38% more comparisons than in the
best case. Moreover, its innermost loop is so efficient that it runs faster than
mergesort (and heapsort, another n log n algorithm that we discuss in Chapter
6) on randomly ordered arrays, justifying the name given to the algorithm by its
inventor, the prominent British computer scientist C.A.R. Hoare.2
2. The young Hoare invented his algorithm while trying to sort words of a Russian dictionary for a
machine translation project from Russian to English. Says Hoare, "My first thought on how to do
r
'
'
.
.
.
134 Divide-and-Conquer
Given the importance of quicksort, there have been persistent efforts over the
years to refine the basic algorithm. Among several improvements discovered by
researchers are: better pivot selection methods (such as the median-of-three par-
titioning that uses as a pivot the median of the leftmost, rightmost, and the middle
element of the array); switching to a simpler sort on smaller subfiles; and recur-
sion elimination (so-called nonrecursive quicksort). According toR. Sedgewick
[Sed98], the world's leading expert on quicksort, these improvements in combi-
nation can cut the running time of the algorithm by 20%-25%.
We should also point out that the idea of partitioning can be useful in ap-
plications other than sorting. In particular, it underlines a fast algorithm for the
important selection problem discussed in Section 5.6.
-----Exercises 4.2 - - - - - - - - - - - - - - - -
1. Apply quicksort to sort the list
E, X, A, M, P, L, E
in alphabetical order. Draw the tree of the recursive calls made.
2. For the partitioning procedure outlined in Section 4.2:
a. Prove that if the scanning indices stop while pointing to the same element,
i.e., i = j, the value they are pointing to must be equal top.
b. Prove that when the scanning indices stop, j cannot point to an element
more than one position to the left of the one pointed to by i.
c. Why is it worth stopping the scans after encountering an element equal to
the pivot?
3. Is quicksort a stable sorting algorithm?
4. Give an example of an array of n elements for which the sentinel mentioned
in the text is actually needed. What should be its value? Also explain why a
single sentinel suffices for any input.
5. For the version of quicksort given in the text:
a. Are arrays made up of all equal elements the worst-case input, the best-
case input, or neither?
b. Are strictly decreasing arrays the worst-case input, the best-case input, or
neither?
6. a. For quicksort with the median-of-three pivot selection, are increasing ar-
rays the worst-case input, the best-case input, or neither?
this was bubblesort and, by an amazing stroke of luck, my second thought was Quicksort." It is hard to
disagree with his overall assessment: "I have been very lucky. What a wonderful way to start a career
in Computing, by discovering a new sorting algorithm!" [Hoa96]
4.3 Binary Search 135
K
t
A[O] ... A[m- 1] A[m] A[m + 1] ... A[n -1].
search here if search here if
K<A[m] K>A[m]
index 0 1 2 3 4 5 6 7 8 9 10 11 12
value 3 II4 127131 139 l42lss 17o 1741 s1lss 193 l9sl
iteration 1 m r
iteration 2 m r
iteration 3 l,m r
The standard way to analyze the efficiency of binary search is to count the
number of times the search key is compared with an element of the array. More-
over, for the sake of simplicity, we will count the so-called three-way comparisons.
This assumes that after one comparison of K with A[m], the algorithm can deter-
mine whether K is smaller, equal to, or larger than A[m ].
How many such comparisons does the algorithm make on an array of n
elements? The answer obviously depends not only on n but also on the specifics of
a particular instance of the problem. Let us find the number of key comparisons
in the worst case C'""'·"(n). The worst-case inputs include all arrays that do not
contain a given search key (and, in fact, some cases of successful searches as well).
Since after one comparison the algorithm faces the same situation but for an array
half the size, we get the following recurrence relation for Cwa.·"(n):
(Stop and convince yourself that 11j2 must be, indeed, rounded down and that the
initial condition must be written as specified.)
As we discussed in Section 2.4, the standard way of solving recurrences such
as recurrence (4.2) is to assume that 11 = 2k and solve the resulting recurrence
by backward substitutions or another method. We leave this as a straightforward
exercise to obtain the solution
(4.3)
Actually, one can prove that the solution given by formula (4.3) for 11 = 2k can be
tweaked to get a solution valid for an arbitrary positive integer 11:
(4.4)
-----Exercises 4 . 3 - - - - - - - - - - - - - - -
1. a. What is the largest number of key comparisons made by binary search in
searching for a key in the following array?
b. List all the keys of this array that will require the largest number of key
comparisons when searched for by binary search.
c. Find the average number of key comparisons made by binary search in a
successful search in this array. (Assume that each key is searched for with
the same probability.)
d. Find the average number of key comparisons made by binary search in an
unsuccessful search in this array. (Assume that searches for keys in each of
the 14 intervals formed by the array's elements are equally likely.)
~
I 4.4 Binary Tree Traversals and Related Properties 139
Since the definition itself divides a binary tree into two smaller structures of
the same type, the left subtree and the right subtree, many problems about binary
trees can be solved by applying the divide-conquer technique. As an example, let
us consider a recursive algorithm for computing the height of a binary tree. Recall
that the height is defined as the length of the longest path from the root to a leaf.
Hence, it can be computed as the maximum of the heights of the root's left and
right subtrees plus 1. (We add 1 to account for the extra level of the root.) Also
note that it is convenient to define the height of the empty tree as -1. Thus, we
have the following recursive algorithm.
ALGORITHM Height(T)
//Computes recursively the height of a binary tree
//Input: A binary tree T
//Output: The height ofT
ifT = 0 return -1
else return max(Height(TL), Height(TR)} + 1
r
4.4 Binary Tree Traversals and Related Properties 141
(a) (b)
FIGURE 4.5 (a) Binary tree. (b) Its extension. Internal nodes are shown as circles;
external nodes are shown as squares.
x=n+l. (4.5)
To prove this formula, consider the total number of nodes, both internal and
external. Since every node, except the root, is one of the two children of an internal
node, we have the equation
2n + l=x +n,
which immediately implies equation (4.5).
Note that equation (4.5) also applies to any nonempty full binary tree, in
which, by definition, every node has either zero or two children: for a full binary
tree, n and x denote the numbers of parental nodes and leaves, respectively.
Returning to algorithm Height, the number of comparisons to check whether
the tree is empty is
C(n)=n+x=2n+l,
while the number of additions is
A(n) = n.
i
142 Divide-and-Conquer
b c Preorder: a, b, d, g, e, c, f
Inorder: d, g, b, e, a, f, c
d e f Postorder: g, d, e, b, f, c, a
The most important divide-and-conquer algorithms for binary trees are the
three classic traversals: preorder, inorder, and postorder. All three traversals visit
nodes of a binary tree recursively, i.e., by visiting the tree's root and its left and
right subtrees. They differ just by the timing of the root's visit:
In the preorder traversal, the root is visited before the left and right subtrees
are visited (in that order).
In the inorder traversal, the root is visited after visiting its left subtree but
before visiting the right subtree.
In the postorder traversal, the root is visited after visiting the left and right
subtrees (in that order).
These traversals are illustrated in Figure 4.6. Their pseudocodes are quite
straightforward, repeating the descriptions given above. (These traversals are also
a standard feature of data structures textbooks.) As to their efficiency analysis, it
is identical to the above analysis of the Height algorithm because a recursive call
is made for each node of an extended binary tree.
Finally, we should note that, obviously, not all questions about binary trees
require traversals of both left and right subtrees. For example, the find and insert
operations for a binary search tree require processing only one of the two subtrees.
Hence, they should be considered not as applications of divide-and-conquer but
rather as examples of the variable-size decrease techuique discussed in Section 5.6.
-----Exercises 4 . 4 - - - - - - - - - - - - - - - -
1. Design a divide-and-conquer algorithm for computing the number of levels
in a binary tree. (In particular, the algorithm must return 0 and l for the
empty and single-node trees, respectively.) What is the efficiency class of your
algorithm?
4.4 Binary Tree Traversals and Related Properties 143
ALGORITHM LeafCounter(T)
//Computes recursively the number of leaves in a binary tree
//Input: A binary tree T
//Output: The number of leaves in T
if T = 0 return 0
else return LeafCounter(T1) + LeafCounter(TR)
b c
d e f
144 Divide-and-Conquer
each internal node. Similarly, the external path length E of an extended binary
tree is defined as the sum of the lengths of the paths-taken over all external
nodes-from the root to each external node. Prove that E = I + 2n where n
is the number of internal nodes in the tree.
9. Write a program for computing the internal path length of an extended binary
tree. Use it to investigate empirically the average number of key comparisons
for searching in a randomly generated binary search tree.
10. Chocolate bar puzzle Given an n-by-m chocolate bar, you need to break it
into nm r-by-r pieces. You can break a bar only in a straight line, and only one
bar can be broken at a time. Design an algorithm that solves the problem with
the minimum number of bar breaks. What is this minimum number? Justify
your answer by using properties of a binary tree.
2 * 4 + 3 * 1 = (2 + 3) * (1 + 4) - 2 * 1- 3 * 4.
Of course, there is nothing special about the numbers we just multiplied.
For any pair of two-digit integers a = a1a0 and b = b 1b0 , their product c can be
computed by the formula
n becomes one. It can also be stopped when we deem n small enough to multiply
the numbers of that size directly.
How many digit multiplications does this algorithm make? Since multiplica-
tion of n-digit numbers requires three multiplications of n/2-digit numbers, the
recurrence for the number of multiplications M (n) will be
(On the last step, we took advantage of the following property of logarithms:
aiogh c = clogb a.)
You should keep in mind that for moderately large integers, this algorithm will
probably run longer than the classic one. Brassard and Bratley ([Bra96], pp. 70-
71) report that in their experiments the divide-and-conquer algorithm started to
outperform the pen-and-pencil method on integers over 600 digits long. If you
program in an object-oriented language such as Java, C++, or Smalltalk, you
should also be aware that these languages have special classes for dealing with
large integers.
= ["oo
aw
"m] *[boo
a11
bOl]
bw bn
- [ m1+~-~+m7
+
m2 m4 m1
m3+~
+ m3 - m2 + m6
]
'
4.5 Multiplication of Large Integers and Strassen's Matrix Multiplication 147
where
m1 = (aoo +au) * (boo+ b1 tl
mz = (aw +au)* boo
m3 ="no* (boJ - h11l
m 4 = a 11 * (b10- h0o)
ms = (aoo + "tnl * bu
m6 = (aw- "ool * (boo+ h01)
m7 = (aot -au)* (bto + bu).
Thus, to multiply two 2-by-2 matrices, Strassen's algorithm makes seven multipli-
cations and 18 additions/subtractions, whereas the brute-force algorithm requires
eight multiplications and four additions. These numbers should not lead us to mul-
tiplying 2-by-2 matrices by Strassen's algorithm. Its importance stems from its
asymptotic superiority as matrix order n goes to infinity.
Let A and B be two n-by-n matrices where n is a power of two. (If n is not a
power of two, matrices can be padded with rows and columns of zeros.) We can
divide A, B, and their product C into four n /2-by-n /2 submatrices each as follows:
[
Coo
C01] = [~] * [--+---Boo
B01]
Cto C 11 A 10 I A 11 B10 Bu
It is not difficult to verify that one can treat these submatrices as numbers to get the
correct product. For example, C00 can be computed either as A00 * B00 + A01 * Bw
or as M 1 + M4 - Ms + M 7 where M1, M4, M 5, and M7 are found by Strassen's
formulas, with the numbers replaced by the corresponding submatrices. If the
seven products of n /2-by-n /2 matrices are computed recursively by the same
method, we have Strassen's algorithm for matrix multiplication.
Let us evaluate the asymptotic efficiency of this algorithm. If M (n) is the
number of multiplications made by Strassen's algorithm in multiplying two n-by-n
matrices (where n is a power of2), we get the following recurrence relation for it:
M(n)=7M(n/2) forn>l, M(l)=l.
Strassen's algorithm. To multiply two matrices of order 11 > 1, the algorithm needs
to multiply seven matrices of order 11/2 and make 18 additions of matrices of size
n/2; when n = 1, no additions are made since two numbers are simply multiplied.
These observations yield the following recurrence relation:
Though one can obtain a closed-form solution to this recurrence (see Problem
8), here we simply establish the solution's order of growth. According to the
Master Theorem stated in the beginning of the chapter, A(n) E 8(n 10g, 7). In other
words, the number of additions has the same order of growth as the number
of multiplications. This puts Strassen's algorithm in 8(11 10g2 7 ), which is a better
efficiency class than 8(n 3) of the brute-force method.
Since the time of Strassen's discovery, several other algorithms for multiplying
two 11-by-n matrices of real numbers in O(n") time with progressively smaller
constants a have been invented. The fastest algorithm so far is that of Coopersmith
and Winograd [Coo87], with its efficiency in 0(11 2376 ). The decreasing values of
the exponents have been obtained at the expense of increasing complexity of these
algorithms. Because of large multiplicative constants, none of them is of practical
value. However, they are interesting from a theoretical point of view. Although
these algorithms get closer and closer to the best theoretical lower bound known
for matrix multiplication, which is n 2 multiplications, the gap between this bound
and the best available algorithm remains unresolved. It is also worth mentioning
that matrix multiplication is known to be computationally equivalent to some
other important problems such as solving systems of linear equations.
-----Exercises 4 . 5 - - - - - - - - - - - - - - - -
1. Wbat are the smallest and largest numbers of digits the product of two decimal
n-digit integers can have?
2. Compute 2101 * 1130 by applying the divide-and-conquer algorithm outlined
in the text.
3. a. Prove the equality a log, c = c10gb a, which was used twice in Section 4.5.
b. Wby is 11logz 3 better than 3Iog,, as a closed-form formula for M(n)?
4. a. Why did we not include multiplications by 10" in the multiplication count
M(11) of the large-integer multiplication algorithm?
b. In addition to assuming that 11 is a power of 2, we made, for the sake of
simplicity, another, more subtle, assumption in setting up a recurrence
relation for M (11), which is not always true (it does not change the final
answer, however). What is this assumption?
4.6 Closest-Pair and Convex-Hull Problems by Divide-and-Conquer 149
1 0 2 1] [0 1
4 1 1 0 2 1 0
0 41]
[ 0130*2 0 1 1
5 0 2 1 1 3 5 0
exiting the recursion when n = 2, i.e., computing the products of 2-by-2 ma-
trices by the brute-force algorithm.
8. Solve the recurrence for the number of additions required by Strassen's algo-
rithm. (Assume that n is a power of 2.)
9. V. Pan [Pan78] has discovered a divide-and-conquer matrix multiplication
algorithm that is based on multiplying two 70-by-70 matrices using 143,640
multiplications. Find the asymptotic efficiency of Pan's algorithm (you may
ignore additions) and compare it with that of Strassen's algorithm.
10. Practical implementations of Strassen 's algorithm usually switch to the brute-
force method after matrix sizes become smaller than some "crossover point."
Run an experiment to determine such crossover point on your computer
system.
Closest-Pair Problem
Let Pt = (xt, y1), ... , Pn = (xn, y,) be a setS of n points in the plane, where n,
for simplicity, is a power of two. With no loss of generality, we can assume that
the points are ordered in ascending order of their x coordinates. (If they were not,
we can sort them in O(n log n) time, e.g., by mergesort.) We can divide the points
150 Divide-and-Conquer
given into two subsets S1 and S2 of 11(2 points each by drawing a vertical line x = c
so that n/2 points lie to the left of or on the line itself, and 11/2 points lie to the
right of or on the line. (One way of finding an appropriate value for constant c for
doing this is to use the median I"' of the x coordinates.)
Following the divide-and-conquer approach, we can find recursively the clos-
est pairs for the left subset S1 and the right subset S2. Let d1 and d2 be the smallest
distances between pairs of points in S1 and S2, respectively, and let d = min{d1o
d2 ). Unfortunately, d is not necessarily the smallest distance between all pairs of
points in S1 and S2 because a closer pair of points can lie on the opposite sides
of the separating line. So, as a step of combining the solutions to the smaller sub-
problems, we need to examine such points. Obviously, we can limit our attention
to the points in the symmetric vertical strip of width 2d since the distance between
any other pair of points is greater than d (Figure 4.7a).
Let C1 and C2 be the subsets of points in the left and right parts of the strip,
respectively. Now, for every point P(x, y) in C1o we need to inspect points in C2 that
may be closer toP than d. Obviously, such points must have their y coordinates in
the interval [y - d, y + d]. The critical insight here is an observation that there can
be no more than six such points because any pair of points in C2 is at least d apart
from each other. (Recall that d ::: d2 where d2 is the smallest distance between
pairs of points to the right of the dividing line.) The worst case is illustrated in
Figure 4.7b.
Another important observation is that we can maintain lists of points in C1
and C2 sorted in ascending order of their y coordinates. (You can think of these
lists as projections of the points on the dividing line.) Moreover, this ordering can
be maintained not by resorting points on each iteration but rather by merging two
previously sorted lists (see algorithm Merge in Section 4.1). We can process the C1
points sequentially while a pointer into the C2 list scans an interval of width 2d to
fetch up to six candidates for computing their distances to a current point P of the
C1 list. The time M(11) for this "merging" of solutions to the smaller subproblems
is in 0(11).
We have the following recurrence for T (n), the running time of this algorithm
on n presorted points:
T(n) = 2T(11/2) + M(n).
Applying the 0 version of the Master Theorem (with a= 2, b = 2, and d = 1),
we get T (n) E 0 (11 log 11). The possible necessity to presort input points does not
change the overall efficiency class if sorting is done by a O(n log n) algorithm. In
fact, this is the best efficiency class we can achieve because it has been proved that
any algorithm for this problem must be in i:2(11log 11) (see [Pre85], p. 188).
Convex-Hull Problem
Let us revisit the convex-hull problem introduced in Section 3.3: fmd the smallest
convex polygon that contains 11 given points in the plane. We consider here a
4.6 Closest-Pair and Convex-Hull Problems by Divide-and-Conquer 151
X= C
•
•
•
•
"k •
•
•
•
d d
(a)
P,
(b)
FIGURE 4.7 (a) Idea of the divide-and-conquer algorithm for the closest-pair problem.
(b) The six points that may need to be examined for point P.
• • •
• •
• •
(Figure 4.8). Let P;P n be the straight line through points P1 and Pn directed from
P1 to P.. Tbis line separates the points of S into two sets: S1 is the set of points to
the left of or on this line and S2 is the set of points to the right of or on this line.
(We say that point p 3 is to the left of the line P1P2 directed from point p 1 to point
P2 if PtPzP 3 forms a counterclockwise cycle. Later, we cite an analytical way to
check this condition based on checking the sign of a determinant formed by the
coordinates of the three points.) The points of S on the line P;P "' other than P1
and Pn, cannot be extreme points of the convex hull and hence are excluded from
further consideration.
The boundary of the convex hull of S is made up of two polygonal chains:
an "upper" boundary and a "lower" boundary. The "upper" boundary, called the
upper hull, is a sequence of line segments with vertices at P1, some of the points
in S1 (if S1 is not empty), and Pn- The "lower" boundary, called the lower hull, is
a sequence of line segments with vertices at P1, some of the points in S2 (if S2 is
not empty) and Pn-
The fact that the convex hull of the entire set S is composed of the upper and
lower hulls, which can be constructed independently and in a similar fashion, is a
very useful observation that is exploited by several algorithms for this problem.
For concreteness, let us discuss how quickhull proceeds to construct the upper
hull; the lower hull can be constructed in the same manner. If S1 is empty, the upper
hull is simply the line segment with the endpoints at P 1 and P.. If S1 is not empty,
the algorithm identifies vertex p max in sj, which is the farthest from the line P;P n
(Figure 4.9) If there is a tie, the point that maximizes the angle L PmaxPJ Pn can
be selected. (Note that point Pmax maximizes the area of the triangle with two
vertices at P1 and Pn and the third at some other point of SJ-) Then the algorithm
identifies all the points of set S1 that are to the left of the line P;P max; these are
the points that, along with P1 and Pmax• will make up the set St.!· The points of St
4.6 Closest-Pair and Convex-Hull Problems by Divide-and-Conquer 153
• •
• • •
•
to the left ofthe line p;;:;;P, will make up, along with Pmax and P,. the set S1.2. It
is not difficult to prove that
ill Pmax is a vertex of the upper hull;
ill the points inside /',. P1 Pmax P, cannot be vertices of the upper hull (and hence
can be eliminated from further consideration); and
., there are no points to the left of both lines P;P max and p;;:;;P,.
Therefore, the algorithm can continue constructing the upper hulls of ? 1 U Su U
Pmax and Pmax U S1.2 U P, recursively and then simply concatenate them to getthe
upper hull of the entire set P 1 U S1 UP,.
Now we have to figure out how the algorithm's geometric operations can be
implemented. Fortunately, we can take advantage of the following very useful fact
from analytical geometry: if p 1 = (x1, y 1), p2 = (x 1, y 1), and p 3 = (x3 , y 3 ) are three
arbitrary points in the Cartesian plane, then the area of the triangle !',.p 1p 2 p 3 is
equal to one half of the magnitude of the determinant
1
1 = XtYz + x3Y1 + XzY3- x3Y2- XzYl- XJY3·
1
while the sign of this expression is positive if and only if the point P3 = (x3, Y3)
is to the left of the line p;P,. Using this formula, we can cheek in constant time
whether a point lies to the left of the line determined by two other points as well
as find the distance from the point to the line.
Quickhull has the same 8 (n 2 ) worst -case efficiency as quicksort (Problem 8
in the exercises). In the average case, however, we should expect a much better
performance. First, the algorithm should benefit from the quicksort-like savings
from the on-average balanced split of the problem into two smaller subproblems.
Second, a siginificant fraction of the points-namely those inside b. P1 PmaxPn (see
154 Divide-and-Conquer
-----Exercises 4J5 - - - - - - - - - - - - - - - -
1. a. For the one-dimensional version of the closest-pair problem, i.e., for the
problem of finding two closest numbers among a given set of n real num-
bers, design an algorithm that is directly based on the divide-and-conquer
technique and determine its efficiency class.
b. Is it a good algorithm for this problem?
2. Consider the version of the divide-and-conquer two-dimensional closest-pair
algorithm in which we simply sort each of the two sets C1 and C2 in ascending
order of their y coordinates on each recursive call. Assuming that sorting is
done by mergesort, set up a recurrence relation for the running time in the
worst case and solve it for n = 2k
3. Implement the divide-and-conquer closest-pair algorithm, outlined in this
section, in the language of your choice.
4. Find on the Web a visualization of an algorithm for the closest-pair problem.
What algorithm does this visualization represent?
5. The Voronoi polygon for a point P of a setS of points in the plane is defined
to be the perimeter of the set of all points in the plane closer to P than to any
other point in S. The union of all the Voronoi polygons of the points in S is
called the Voronoi diagram of S.
a. What is the Voronoi diagram for a set of three points?
b. Find on the Web a visualization of an algorithm for generating the Voronoi
diagram and study a few examples of such diagrams. Based on your obser-
vations, can you tell how the solution to the previous question is general-
ized to the general case?
6. Explain how one can find point Pmax in the quickhull algorithm analytically.
i7,, What is the best-case efficiency of quickhull?
\
·s:; Give a specific example of inputs that make the quickhull algorithm run in
quadratic time.
9. Implement the quickhull algorithm in the language of your choice.
10. Shortest path around There is a fenced area in the two-dimensional Eu-
clidean plane in the shape of a convex polygon with vertices at points P1 (x 1 , y 1),
P2(x 2, y 2), ... , PnCxn, Ynl (not necessarily in this order). There are two more
Summary 155
points, A(xA, YA) and B(x 8 , y 8 ), such that xA < min{x1 , x 2 , ... , x,) and x 8 >
max{x 1, x 2 , ... , x,). Design a reasonably efficient algorithm for computing
the length of the shortest path between A and B. [0Ro98], p. 68
SUMMARY
" Binary search is a 0 (log 11) algorithm for searching in sorted arrays. It is
an atypical example of an application of the divide-and-conquer technique
because it needs to solve just one problem of half the size on each of its
iterations.
,. Strassen 's algorithm needs only seven multiplications to multiply two 2-by-
2 matrices but requires more additions than the definition-based algorithm.
By exploiting the divide-and-conquer technique, this algorithm can multiply
two n-by-n matrices with about n2 ·807 multiplications.
" The divide-and-conquer technique can be successfully applied to two impor-
tant problems of computational geometry: the closest-pair problem and the
convex-hnll problem.