Algorithms
Algorithms
a problem of size n
subproblem 1 subproblem 2
of size n/2 Divide of size n/2
a solution to a solution to
subproblem 1 subproblem 2
a solution to
the original problem
Index: 1 2 3 4 5 6 7 8 9
Array: 22 13 -5 -8 15 60 17 31 47
(1)
Rmaxmin(1, 9, 60, -8)
(6)
1, 5, 22, -8 6, 9, 60, 17
(2) (5) (7) (8)
1, 2, 22, 13 3, 3, -5, -5
T(n) = (1) if n = 1 or 2
2T(n/2) + (1) if n > 2
equivalently
T(n) = b if n = 1 or 2
2T(n/2) + b if n > 2
a problem of size n
subproblem 1 subproblem 2
of size n/2 Divide of size n/2
a solution to a solution to
subproblem 1 subproblem 2
a solution to
the original problem
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
A 13 -3 -25 20 -3 -16 -23 18 20 -7 12 -5 -22 15 -4 7
maximum subarray
1 -4 -3
What is the brute-
-4 3 -1
force time?
Max! 3 2 5
1 -4 3 0
-4 3 2 1
1 -4 3 2 2
Brute-Force Algorithm
Example: 2 -6 -1 3 -1 2 -2
sum from A[1]: 2 -4 -5 -2 -3 -1 -3
sum from A[2]: -6 -7 -4 -5 -3 -5
sum from A[3]: -1 2 1 3 1
sum from A[4]: 3 2 4 2
sum from A[5]: -1 1 -1
sum from A[6]: 2 0
sum from A[7]: -2
mid +1
A[mid+1..j]
mid +1 j
A[i..mid]
S[5 .. 5] = -3
S[4 .. 5] = 17 (max-left = 4)
S[3 .. 5] = -8
S[2 .. 5] = -11
S[1 .. 5] = 2
mid =5
1 2 3 4 5 6 7 8 9 10
S[6 .. 6] = -16
S[6 .. 7] = -39
S[6 .. 8] = -21
S[6 .. 9] = (max-right = 9) -1
S[6..10] = -8
maximum subarray crossing mid is S[4..9] = 16
Dr. Md. Abul Kashem Mia, Professor, CSE Dept, BUET
Divide-and-Conquer Algorithm
FIND-MAXIMUM-SUBARRAY (A, low, high)
if high == low
return (low, high, A[low]) // base case: only one element
else mid = low high / 2
(left-low, left-high, left-sum) =
FIND-MAXIMUM-SUBARRAY(A, low, mid)
(right-low, right-high, right-sum) =
FIND-MAXIMUM-SUBARRAY(A, mid + 1, high)
(cross-low, cross-high, cross-sum) =
FIND-MAX-CROSSING-SUBARRAY(A, low, mid, high)
if left-sum ≧ right-sum and left-sum ≧ cross-sum
return (left-low, left-high, left-sum)
elseif right-sum ≧ left-sum and right-sum ≧ cross-sum
return (right-low, right-high, right-sum)
else return (cross-low, cross-high, cross-sum)
Initial call: FIND-MAXIMUM-SUBARRAY (A, 1, n)
Dr. Md. Abul Kashem Mia, Professor, CSE Dept, BUET
Divide-and-Conquer Algorithm
Analyzing time complexity
FIND-MAX-CROSSING-SUBARRAY : (n),
where n = high low + 1
FIND-MAXIMUM-SUBARRAY
1 if n 1,
T n
2T n / 2 n if n 1.
Merge sort
Divide step is trivial – just split the list into two equal parts
Quick sort
Work is carried out in the divide step using a pivot element
Partition
7 2 9 43 8 6 1 1 2 3 4 6 7 8 9
7 2 9 4 2 4 7 9 3 8 6 1 1 3 8 6
7 2 2 7 9 4 4 9 3 8 3 8 6 1 1 6
Merge Sort 7
Execution Example
7 29 4 2 4 7 9 3 8 6 1 1 3 8 6
7 2 2 7 9 4 4 9 3 8 3 8 6 1 1 6
Merge Sort 8
Execution Example
7 29 4 2 4 7 9 3 8 6 1 1 3 8 6
722 7 9 4 4 9 3 8 3 8 6 1 1 6
Merge Sort 9
Execution Example
7 29 4 2 4 7 9 3 8 6 1 1 3 8 6
722 7 9 4 4 9 3 8 3 8 6 1 1 6
Merge Sort 10
Execution Example
7 29 4 2 4 7 9 3 8 6 1 1 3 8 6
722 7 9 4 4 9 3 8 3 8 6 1 1 6
Merge Sort 11
Execution Example
Merge
7 2 9 43 8 6 1 1 2 3 4 6 7 8 9
7 29 4 2 4 7 9 3 8 6 1 1 3 8 6
722 7 9 4 4 9 3 8 3 8 6 1 1 6
Merge Sort 12
Execution Example
7 29 4 2 4 7 9 3 8 6 1 1 3 8 6
722 7 9 4 4 9 3 8 3 8 6 1 1 6
Merge Sort 13
Execution Example
Merge
7 2 9 43 8 6 1 1 2 3 4 6 7 8 9
7 29 4 2 4 7 9 3 8 6 1 1 3 8 6
722 7 9 4 4 9 3 8 3 8 6 1 1 6
Merge Sort 14
Execution Example
7 29 4 2 4 7 9 3 8 6 1 1 3 6 8
722 7 9 4 4 9 3 8 3 8 6 1 1 6
Merge Sort 15
Execution Example
Merge
7 2 9 43 8 6 1 1 2 3 4 6 7 8 9
7 29 4 2 4 7 9 3 8 6 1 1 3 6 8
722 7 9 4 4 9 3 8 3 8 6 1 1 6
Merge Sort 16
Merge Sort: Running Time
T(n) = (1) if n = 1
2T(n/2) + (n) if n > 1
equivalently
T(n) = b if n = 1
2T(n/2) + bn if n > 1
Draw the recursion tree for the recurrence relation and look for a
pattern:
b if n 1
T ( n)
2T (n / 2) bn if n 2
time
depth T’s size
0 1 n bn
1 2 n/2 bn
i 2i n/2i bn
… … … …
pivot
● Iteration Method
● Master Method
● Recursion Tree Method
c n 1
n
T (n) aT
cn n 1
b
● T(n) =
aT(n/b) + cn
a(aT(n/b/b) + cn/b) + cn
a2T(n/b2) + cna/b + cn
a2T(n/b2) + cn(a/b + 1)
a2(aT(n/b2/b) + cn/b2) + cn(a/b + 1)
a3T(n/b3) + cn(a2/b2) + cn(a/b + 1)
a3T(n/b3) + cn(a2/b2 + a/b + 1)
…
akT(n/bk) + cn(ak-1/bk-1 + ak-2/bk-2 + … + a2/b2 + a/b + 1)
● So we have
■ T(n) = akT(n/bk) + cn(ak-1/bk-1 + ... + a2/b2 + a/b + 1)
● For n/bk = 1
■ n = bk → k = logb n
■ T(n) = akT(1) + cn(ak-1/bk-1 + ... + a2/b2 + a/b + 1)
= akc + cn(ak-1/bk-1 + ... + a2/b2 + a/b + 1)
= cak bk /bk + cn(ak-1/bk-1 + ... + a2/b2 + a/b + 1)
= cn ak /bk + cn(ak-1/bk-1 + ... + a2/b2 + a/b + 1)
= cn(ak/bk + ... + a2/b2 + a/b + 1)
● So with k = logb n
■ T(n) = cn(ak/bk + ... + a2/b2 + a/b + 1)
● What if a = b?
■ T(n) = cn(k + 1)
= cn(logb n + 1)
= (n log n)
● So with k = logb n
■ T(n) = cn(ak/bk + ... + a2/b2 + a/b + 1)
● What if a < b?
● So with k = logb n
■ T(n) = cn(ak/bk + ... + a2/b2 + a/b + 1)
● What if a < b?
■ Recall that (xk + xk-1 + … + x + 1) = (xk+1 -1)/(x-1)
● So with k = logb n
■ T(n) = cn(ak/bk + ... + a2/b2 + a/b + 1)
● What if a < b?
■ Recall that (xk + xk-1 + … + x + 1) = (xk+1 -1)/(x-1)
■ So:
a k a k 1 a
k 1 1
a b k 1 1
1 a b
k 1
1
k
b b b a b 1 1 a b 1 a b
● So with k = logb n
■ T(n) = cn(ak/bk + ... + a2/b2 + a/b + 1)
● What if a < b?
■ Recall that (xk + xk-1 + … + x + 1) = (xk+1 -1)/(x-1)
■ So:
a k a k 1 a
k 1 1
a b k 1 1
1 a b
k 1
1
k
b b b a b 1 1 a b 1 a b
● So with k = logb n
■ T(n) = cn(ak/bk + ... + a2/b2 + a/b + 1)
● What if a > b?
● So with k = logb n
■ T(n) = cn(ak/bk + ... + a2/b2 + a/b + 1)
● What if a > b?
a k a k 1 a
k 1 1
a b k 1 1
a b
k
k
b b b a b 1
● So with k = logb n
■ T(n) = cn(ak/bk + ... + a2/b2 + a/b + 1)
● What if a > b?
a k a k 1 a
k 1 1
a b k 1 1
a b
k
k
b b b a b 1
■ T(n) = cn · (ak / bk)
● So with k = logb n
■ T(n) = cn(ak/bk + ... + a2/b2 + a/b + 1)
● What if a > b?
a k a k 1 a
k 1 1
a b k 1 1
a b
k
k
b b b a b 1
■ T(n) = cn · (ak / bk)
= cn · (alogb n / blogb n) = cn · (alogb n / n)
● So with k = logb n
■ T(n) = cn(ak/bk + ... + a2/b2 + a/b + 1)
● What if a > b?
a k a k 1 a
k 1 1
a b k 1 1
a b
k
k
b b b a b 1
■ T(n) = cn · (ak / bk)
= cn · (alogb n / blogb n) = cn · (alogb n / n)
recall logarithm fact: alogb n = nlogb a
● So with k = logb n
■ T(n) = cn(ak/bk + ... + a2/b2 + a/b + 1)
● What if a > b?
a k a k 1 a
k 1 1
a b k 1 1
a b
k
k
b b b a b 1
■ T(n) = cn · (ak / bk)
= cn · (alogb n / blogb n) = cn · (alogb n / n)
recall logarithm fact: alogb n = nlogb a
= cn · (nlogb a / n) = (cn · nlogb a / n)
● So with k = logb n
■ T(n) = cn(ak/bk + ... + a2/b2 + a/b + 1)
● What if a > b?
a k a k 1 a
k 1 1
a b k 1 1
a b
k
k
b b b a b 1
■ T(n) = cn · (ak / bk)
= cn · (alogb n / blogb n) = cn · (alogb n / n)
recall logarithm fact: alogb n = nlogb a
= cn · (nlogb a / n) = (cn · nlogb a / n)
= (nlogb a )
Dr. Md. Abul Kashem Mia, Professor, CSE Dept, BUET
c n 1
n
T ( n) aT
cn n 1
b
● So…
n ab
T ( n) n log b n ab
log b a
n
ab
Recursion tree:
T (n) T (n)
a
T (n/b) T (n/b) … T (n/b) a T (n/b)
h = logbn a
T (n/b2) T (n/b2) … T (n/b2) a2 T (n/b2)
#leaves = ah
… T (1) = alogbn
= nlogba
(log b n ) 1
n log b a T (1)
a i f (n / b i )
i0
Dr. Md. Abul Kashem Mia, Professor, CSE Dept, BUET
Idea of Master Theorem
Thus, we obtained
T(n) = nlogb(a) T(1) + ai f(n/bi)
The proof proceeds by distinguishing three cases:
The first term is dominant:
f(n) = O(nlogb(a)-e)
Each term of the summation is equally dominant:
f(n) = (nlogb(a) )
The second term is dominant and can be bounded by a
geometric series:
f(n) = (nlogb(a)+e)
2. f (n) = (nlogba)
• f (n) and nlogba grow at similar rates.
Solution: T(n) = (nlogba logn).
Activity--Selection Problem
Activity
Thus, B is optimal
Why?
Knapsack Problem
Which items
should I take?
There are n items: the i-th item has value vi and weight wi
Goal:
wixi W and
xivi is maximum
20
$80
---
Item 3 30 +
Item 2 50 50
20 $100
Item 1 30
20 +
10 10 $60
5. w w – xiwi
w – the amount of space remaining in the knapsack (initially w = W)
Item 3 30 $120
50 50 +
Item 2 50
20 $100
Item 1 30
20 + 20 $100
10 10 $60
Etymology.
Dynamic programming = planning over time.
Secretary of Defense was hostile to mathematical research.
Bellman sought an impressive name to avoid confrontation.
Subproblem Overlap
Optimal subproblems to unrelated problems can contain
subproblems in common
Fib(5)
Fib(4) Fib(3)
Fib(1) Fib(0)
Fib(n):
if n = 0 or 1 then return F[n]
if F[n 1] = NIL then F[n 1] := Fib(n 1)
if F[n 2] = NIL then F[n 2] := Fib(n 2)
return ( F[n 1] + F[n 2] )
F returns 3+2 = 5,
0 0 Fib(5)
fills in F[5] with 5
1 1
2 1
NIL returns 2+1 = 3,
Fib(4)
fills in F[4] with 3
3 2
NIL
4 3
NIL returns 1+1 = 2,
Fib(3)
5 5
NIL fills in F[3] with 2
returns 0+1 = 1,
Fib(2)
fills in F[2] with 1
F0 F1 F2 F3 … Fn-2 Fn-1 Fn
Fib(n):
F[0] := 0; F[1] := 1;
for i := 2 to n do
F[i] := F[i 1] + F[i 2]
return F[n]
Can perform application-specific optimizations
e.g., save space by only keeping last two numbers
computed
Example:
X= AB C BDAB
Y= BDCAB A
Proof ?
Xi-1 xi
equal
Yj-1 yj
Xi-1 xi
not equal
Yj-1 yj
m Goal
An order for solving the subproblems (i.e., filling in the array) that
respects the dependencies is row major order:
do the rows from top to bottom
inside each row, go from left to right
Dr. Md. Abul Kashem Mia, Professor, CSE Dept, BUET
Develop a Recursive Solution
LCS(X, Y) = BCG
X=AB C G
Y= BDCAG
1 A
2 B
3 C
4 G
X = ABCG; m = |X| = 4
Y = BDCAG; n = |Y| = 5
Allocate array: c[5, 4]
Dr. Md. Abul Kashem Mia, Professor, CSE Dept, BUET
LCS Example ABCG
j 0 1 2 3 4 5
BDCAG
i yj B D C A G
0 xi 0 0 0 0 0 0
1 A 0
2 B 0
3 C 0
4 G 0
for i = 0 to m c[i, 0] = 0
for j = 1 to n c[0, j] = 0
Dr. Md. Abul Kashem Mia, Professor, CSE Dept, BUET
LCS Example ABCG
j 0 1 2 3 4 5
BDCAG
i yj B D C A G
0 xi 0 0 0 0 0 0
1 A 0 0
2 B 0
3 C 0
4 G 0
if ( xi == yj )
c[i, j] = c[i-1, j-1] + 1
else c[i, j] = max( c[i-1, j], c[i, j-1] )
if ( xi == yj )
c[i, j] = c[i-1, j-1] + 1
else c[i, j] = max( c[i-1, j], c[i, j-1] )
if ( xi == yj )
c[i, j] = c[i-1, j-1] + 1
else c[i, j] = max( c[i-1, j], c[i, j-1] )
if ( xi == yj )
c[i, j] = c[i-1, j-1] + 1
else c[i, j] = max( c[i-1, j], c[i, j-1] )
if ( xi == yj )
c[i, j] = c[i-1, j-1] + 1
else c[i, j] = max( c[i-1, j], c[i, j-1] )
if ( xi == yj )
c[i, j] = c[i-1, j-1] + 1
else c[i, j] = max( c[i-1, j], c[i, j-1] )
if ( xi == yj )
c[i, j] = c[i-1, j-1] + 1
else c[i, j] = max( c[i-1, j], c[i, j-1] )
if ( xi == yj )
c[i, j] = c[i-1, j-1] + 1
else c[i, j] = max( c[i-1, j], c[i, j-1] )
if ( xi == yj )
c[i, j] = c[i-1, j-1] + 1
else c[i, j] = max( c[i-1, j], c[i, j-1] )
if ( xi == yj )
c[i, j] = c[i-1, j-1] + 1
else c[i, j] = max( c[i-1, j], c[i, j-1] )
if ( xi == yj )
c[i, j] = c[i-1, j-1] + 1
else c[i, j] = max( c[i-1, j], c[i, j-1] )
if ( xi == yj )
c[i, j] = c[i-1, j-1] + 1
else c[i, j] = max( c[i-1, j], c[i, j-1] )
So far, we have just found the length of LCS, but not LCS itself.
We can modify this algorithm to make it output an LCS of X
and Y.
Each c[i, j] depends on c[i-1, j-1], or c[i-1, j] and c[i, j-1].
For each c[i, j] we can say how it was acquired.
Remember that
c[i 1, j 1] 1 if x[i ] y[ j ],
c[i, j ]
max(c[i, j 1], c[i 1, j ]) otherwise
Greedy solution is
optimal for any amount and “normal’’ set of denominations
The greedy method would not work if we did not have 5¢ coins
For 31 cents, the greedy method gives seven coins (25+1+1+1+1+1+1),
but we can do it with four (10+10+10+1)
The greedy method also would not work if we had a 21¢ coin
For 63 cents, the greedy method gives six coins (25+25+10+1+1+1), but
we can do it with three (21+21+21)
Value 1 2 3 4 5 6 7 8 9 10
Min # of coins 1 1 1
Value 1 2 3 4 5 6 7 8 9 10
Min # of coins 1 2 1 2 1 2 2 2
Value 1 2 3 4 5 6 7 8 9 10
Min # of coins 1 2 1 2 1 2 3 2 3 2
minNumCoins(M-1) + 1
min minNumCoins(M-3) + 1
minNumCoins(M) =
of
minNumCoins(M-5) + 1
minNumCoins(M-c1) + 1
min minNumCoins(M-c2) + 1
minNumCoins(M) =
of …
minNumCoins(M-cd) + 1
1. RecursiveChange(M, c, d)
2. if M = 0
3. return 0
4. bestNumCoins infinity
5. for i 1 to d
6. if M ≥ ci
7. numCoins RecursiveChange(M – ci , c, d)
8. if numCoins + 1 < bestNumCoins
9. bestNumCoins numCoins + 1
10. return bestNumCoins
77
76 74 70
75 73 69 73 71 67 69 67 63
... ..
70 70 70 70 70
.
Dr. Md. Abul Kashem Mia, Professor, CSE Dept, BUET
We Can Do Better
1. DPChange(M, c, d)
2. bestNumCoins0 0 Running time: O(M*d)
3. for m 1 to M
4. bestNumCoinsm infinity
5. for i 1 to d
6. if m ≥ ci
7. if bestNumCoinsm – ci+ 1 < bestNumCoinsm
8. bestNumCoinsm bestNumCoinsm – ci+ 1
9. return bestNumCoinsM
0 0 1 2 1 2 3 2
0 0 1 2 3 4 5 6
0 1
0 1 0 1 2 1 2 3 2 1
0 1 2 3 4 5 6 7
0 1 2
0 1 2
0 1 2 1 2 3 2 1 2
0 1 2 1 0 1 2 3 4 5 6 7 8
0 1 2 3
0 1 2 1 2 3 2 1 2 3
0 1 2 1 2 0 1 2 3 4 5 6 7 8 9
0 1 2 3 4
0 1 2 1 2 3
c = (1, 3, 7)
0 1 2 3 4 5 M=9
Which items
should I take?
Item 3 30 $120
50 50 50 +
Item 2
20 $100
Item 1 30
20 + 20 $100
10 10 $60
The best subset that has the total weight w, either contains item i
or not.
First case: w <wi. Item i can’t be part of the solution, since if it
was, the total weight would be > w, which is unacceptable.
Second case: w >= wi. Then the item i can be in the solution,
and we choose the case with greater value.
0 0 0 0 0 0 0 0 0 0 0 0
0 first
0 second
i-1 0
i 0
0
n 0
0 0 0 0 0 0 0 0 0 0 0 0
0
0
i-1 0
i 0
0
n 0
1 0 0 12 12 12 12
• Item 2
2 0 10 12 22 22 22
0 • Item 1
3 10 12 22 30 32
0
4 10 15 25 30 37
• Start at P(n, W)
• When you go left-up item i has been taken
• When you go straight up item i has not been taken
0-1 Knapsack Algorithm
for w = 0 to W
P[0, w] = 0
for i = 0 to n Running time: O(n*W)
P[i, 0] = 0
for w = 0 to W
if wi <= w // item i can be part of the solution
if (vi + P[i-1, w-wi] > P[i-1, w])
P[i, w] = vi + P[i-1, w- wi]
else
P[i, w] = P[i-1, w]
else P[i, w] = P[i-1, w] // wi > w
Lookup-Chain(m, p, i, j)
if m[i, j] <
running time O(n 3)
return m[i, j]
if i = = j
m[i, j] = 0
else for k = i to j – 1
q = Lookup-Chain(m, p, i, k) +
Lookup-Chain(m, p, k + 1, j) + pi-1 pk pj
if q < m[i, j]
m[i, j] = q
return m[i, j]
1 2 3 4 5
m:
1 0 GOAL !
2 n/a 0
computing the red
3 n/a n/a 0
square requires the
4 n/a n/a n/a 0 blue ones: to the
left and below.
5 n/a n/a n/a n/a 0
m: 1 2 3 4 5
1 0
2 n/a 0
3 n/a n/a 0
4 n/a n/a n/a 0
5 n/a n/a n/a n/a 0
5 0 5000
6 0