Reading: Chapter 18
Divide-and-conquer is a frequently-useful algorithmic technique tied up in recursion.
We'll see how it is useful in
A divide-and-conquer algorithm has three basic
steps...
Problem SORT:
example:
+----+----+----+----+----+----+----+----+ A = | 19 | 1 | 29 | 30 | 6 | 15 | 2 | 5 | +----+----+----+----+----+----+----+----+ +----+----+----+----+----+----+----+----+ return | 1 | 2 | 5 | 6 | 15 | 19 | 29 | 30 | +----+----+----+----+----+----+----+----+
Algorithm M-Sort(A):
if a's length > 1, then:
return A.
else:
Let AL be the first half of A.
Let AR be the second half of A.
return Merge(M-Sort(AL), M-Sort(AR))
end of if
Algorithm Merge(A, B):
Let nA and nB be the length of arrays A and B.
// C holds merged array
Let C be an array of length nA + nB.
// a,b,c are current positions in A,B,C
Let a, b, and c hold 0.
while a < nA and b < nB, do:
if a < nA and A[a] < B[b], then:
Let C[c] hold A[a].
Add 1 to a and c.
else:
Let C[c] hold B[b].
Add 1 to b and c.
end of if
end of loop
return C.
example:
+----+----+----+----+ | 1 | 19 | 29 | 30 | +----+----+----+----+\ +----+----+----+----+----+----+----+----+ >-->| 1 | 2 | 5 | 6 | 15 | 19 | 29 | 30 | +----+----+----+----+/ +----+----+----+----+----+----+----+----+ | 2 | 5 | 6 | 15 | +----+----+----+----+
Write a recurrence and solve...
T(n) = 2 T(n / 2) + cn
Problem MULTIPLICATION
example:
1980 = a x 2315 = b --------- 9900 1980 5940 + 3960 --------- 4573700 = a x bThis is the algorithm you learned in grade school. Notice it takes O(n^2) time.
We divide each integer into two halves.
aL = 19 | 80 = aR | bL = 23 | 15 = bR aL aR x bL bR ----------------------------- aL bR aR bR + aL bL aR bL ----------------------------- aL bL aL bR + aR bL aR bRSo our algorithm is to compute aL bL, aL bR, aR bL, and aR bR, and add.
T(n) <= 4 T(n / 2) + O(n) T(n) = O(n^2)
Algorithm Divide-Mult(a,b):
if a or b has one digit, then:
return a * b.
else:
Let n be the number of digits in max{a, b}.
Let aL and aR be left and right halves of a.
Let bL and bR be left and right halves of b.
Let x1 hold Divide-Mult(aL, bL).
Let x2 hold Divide-Mult(aL, bR).
Let x3 hold Divide-Mult(aR, bL).
Let x4 hold Divide-Mult(aR, bR).
return x1*10n + (x2 + x3)*10n/2 + x4.
end of if
We can actually get away with just three multiplications!
x1 = aL bL x2 = aR bR x3 = (aL + aR) (bL + bR) aL aR x bL bR ----------------------------- aL bL aL bR + aR bL aR bR x1 x3 - x1 - x2 x2Now our algorithm is to compute x1, x2, and x3, find x3 - x1 - x2, and add.
Algorithm Karatsuba(a,b):
if a or b has one digit, then:
return a * b.
else:
Let n be the number of digits in max{a, b}.
Let aL and aR be left and right halves of a.
Let bL and bR be left and right halves of b.
Let x1 hold Karatsuba(aL, bL).
Let x2 hold Karatsuba(aL + aR, bL + bR).
Let x3 hold Karatsuba(aR, bR).
return x1*10n + (x2 - x1 - x3)*10n/2 + x3.
end of if
Ooooh!
Aaaah!
IN Multiply(1980, 2315) 19 80 23 15 IN Multiply(19, 23) 1 9 2 3 IN Multiply(1, 2) return 2 IN Multiply(9, 3) return 27 IN Multiply(10, 5) 1 0 0 5 IN Multiply(1, 0) return 0 IN Multiply(0, 5) return 0 IN Multiply(1, 5) return 5 5 - 0 - 0 = 5 0 5 0 --- 50 return 50 50 - 27 - 2 = 21 2 21 27 --- 437 return 437 IN Multiply(80, 15) 8 0 1 5 IN Multiply(8, 1) return 8 IN Multiply(0, 5) return 0 IN Multiply(8, 6) return 48 48 - 8 - 0 = 40 8 40 0 ---- 1200 return 1200 IN Multiply(99, 38) 9 9 3 8 IN Multiply(9, 3) return 27 IN Multiply(9, 8) return 72 IN Multiply(18, 11) 1 8 1 1 IN Multiply(1, 1) return 1 IN Multiply(8, 1) return 8 IN Multiply(9, 2) return 18 18 - 8 - 1 = 9 1 9 8 --- 198 return 198 198 - 27 - 72 = 99 27 99 72 ---- 3762 return 3762 3762 - 437 - 1200 = 2125 437 2125 1200 ------- 4583700 return 4583700