CS 3343: Analysis of Algorithms Review for final 7/24/2016 1 Final Exam • Closed book exam • Coverage: the whole semester • Cheat sheet: you are allowed one lettersize sheet, both sides • Monday, May 6, 10:30am – 1:00pm • Basic calculator (no graphing) allowed 7/24/2016 2 Final Exam: Study Tips • Study tips: – Study each lecture – Study the homework and homework solutions – Study the midterm exams • Re-make your previous cheat sheets 7/24/2016 3 Topics covered (1) By reversed chronological order: • Graph algorithms – Representations – MST (Prim’s, Kruskal’s) – Shortest path (Dijkstra’s) – Running time analysis with different implementations 7/24/2016 4 Topics covered (2) • Dynamic programming – – – – – LCS Restaurant location problem Shortest path problem on a grid Other problems How to define recurrence solution, and use dynamic programming to solve it • Greedy algorithm – Unit-profit restaurant location problem – Fractional knapsack problem – Prim’s, Kruskal’s, and Dijkstra’s are also examples of greedy algorithms – How to prove that certain greedy choices are optimal 7/24/2016 5 Topics covered (3) • Hash tables – Division-based hash functions – Multiplication-based hash functions – A universal hash function family • Binary heap and priority queue – Heapify, buildheap, insert, exatractMax, changeKey – Running time 7/24/2016 6 Topics covered (4) • Sorting algorithms – – – – – – – – Insertion sort Merge sort Quick sort Heap sort Linear time sorting: counting sort, radix sort Stability of sorting algorithms Worst-case and expected running time analysis Memory requirement of sorting algorithms • Order statistics – Rand-Select – Worst-case Linear-time selection – Running time analysis 7/24/2016 7 Topics covered (5) • Analysis – Order of growth – Asymptotic notation, basic definition • Limit method • L’ Hopital’s rule • Stirling’s formula – Best case, worst case, average case • Analyzing non-recursive algorithms – Arithmetic series – Geometric series • Analyzing recursive algorithms – Defining recurrence – Solving recurrence • Recursion tree (iteration) method • Substitution method • Master theorem 7/24/2016 8 Review for finals • In chronological order • Only the more important concepts – Very likely to appear in your final • Does not mean to be exclusive 7/24/2016 9 Asymptotic notations • • • • • • O: Big-Oh Ω: Big-Omega Θ: Theta o: Small-oh ω: Small-omega Intuitively: O is like o is like < 7/24/2016 is like is like > is like = 10 Big-Oh • Math: – O(g(n)) = {f(n): positive constants c and n0 such that 0 ≤ f(n) ≤ cg(n) n>n0} – Or: lim n→∞ g(n)/f(n) > 0 (if the limit exists.) • Engineering: – g(n) grows at least as faster as f(n) – g(n) is an asymptotic upper bound of f(n) • Intuitively it is like f(n) ≤ g(n) 7/24/2016 11 Big-Oh • Claim: f(n) = 3n2 + 10n + 5 O(n2) • Proof: 3n2 + 10n + 5 10n2 + 10n + 10 3 x 10 n2 for n 1 Therefore, • Let c = 30 and n0 = 1 • f(n) c n2, n ≥ n0 7/24/2016 12 Big-Omega • Math: – Ω(g(n)) = {f(n): positive constants c and n0 such that 0 ≤ cg(n) ≤ f(n) n>n0} – Or: lim n→∞ f(n)/g(n) > 0 (if the limit exists.) • Engineering: – f(n) grows at least as faster as g(n) – g(n) is an asymptotic lower bound of f(n) • Intuitively it is like g(n) ≤ f(n) 7/24/2016 13 Big-Omega • f(n) = n2 / 10 = Ω(n) • Proof: f(n) = n2 / 10, g(n) = n – g(n) = n ≤ n2 / 10 = f(n) when n ≥ 10 – Therefore, c = 1 and n0 = 10 7/24/2016 14 Theta • Math: – Θ(g(n)) = {f(n): positive constants c1, c2, and n0 such that c1 g(n) f(n) c2 g(n) n n0 n>n0} – Or: lim n→∞ f(n)/g(n) = c > 0 and c < ∞ – Or: f(n) = O(g(n)) and f(n) = Ω(g(n)) • Engineering: – f(n) grows in the same order as g(n) – g(n) is an asymptotic tight bound of f(n) • Intuitively it is like f(n) = g(n) • Θ(1) means constant time. 7/24/2016 15 Theta • Claim: f(n) = 2n2 + n = Θ (n2) • Proof: – We just need to find the three constants c1, c2, and n0 such that – c1n2 ≤ 2n2+n ≤ c2n2 for all n > n0 – A simple solution is c1 = 2, c2 = 3, and n0 = 1 7/24/2016 16 Using limits to compare orders of growth f(n) o(g(n)) • lim f(n) / g(n) = n→∞ 0 c >0 ∞ f(n) O(g(n)) f(n) Θ (g(n)) f(n) Ω(g(n)) f(n) ω (g(n)) 7/24/2016 17 • Compare 2n and 3n • lim 2n / 3n = lim(2/3)n = 0 n→∞ n→∞ • Therefore, 2n o(3n), and 3n ω(2n) 7/24/2016 18 L’ Hopital’s rule lim f(n) / g(n) = lim f(n)’ / g(n)’ n→∞ 7/24/2016 n→∞ If both lim f(n) and lim g(n) goes to ∞ 19 • Compare n0.5 and log n • lim n0.5 / log n = ? n→∞ • • • • 7/24/2016 (n0.5)’ = 0.5 n-0.5 (log n)’ = 1 / n lim (n-0.5 / 1/n) = lim(n0.5) = ∞ Therefore, log n o(n0.5) 20 Stirling’s formula n n n 1 / 2 n n! 2 n 2 n e e n! 7/24/2016 (constant) n n 1/ 2 n e 21 • Compare 2n and n! n n! c nn n lim n lim n n lim c n n 2 n 2 e n 2e n • Therefore, 2n = o(n!) 7/24/2016 22 More advanced dominance ranking 7/24/2016 23 General plan for analyzing time efficiency of a non-recursive algorithm • Decide parameter (input size) • Identify most executed line (basic operation) • worst-case = average-case? • T(n) = i ti • T(n) = Θ (f(n)) 7/24/2016 24 Analysis of insertion Sort Statement InsertionSort(A, n) { for j = 2 to n { key = A[j] i = j - 1; while (i > 0) and (A[i] > key) { A[i+1] = A[i] i = i - 1 } A[i+1] = key } } 7/24/2016 cost time__ c1 c2 c3 c4 c5 c6 0 c7 0 n (n-1) (n-1) S (S-(n-1)) (S-(n-1)) (n-1) 25 Best case Inner loop stops when A[i] <= key, or i = 0 i j 1 sorted Key • Array already sorted n S 1 n (n) j 1 7/24/2016 26 Worst case Inner loop stops when A[i] <= key i j 1 sorted Key • Array originally in reverse order n(n 1) 2 S j 1 2 ... n (n ) 2 j 1 n 7/24/2016 27 Average case Inner loop stops when A[i] <= key i j 1 sorted Key • Array in random order j 1 n n(n 1) E(S ) j (n 2 ) 2 j 1 4 j 1 2 n 7/24/2016 28 Find the order of growth for sums n T (n) j (n ) 2 n T ( n ) log( j ) ? j 1 j 1 n T (n) 2 j ? j 1 n n T (n) j ? j 1 2 ... • How to find out the actual order of growth? – Remember some formulas – Learn how to guess and prove 7/24/2016 29 Arithmetic series • An arithmetic series is a sequence of numbers such that the difference of any two successive members of the sequence is a constant. e.g.: 1, 2, 3, 4, 5 or 10, 12, 14, 16, 18, 20 • In general: a j a j 1 d Or: 7/24/2016 a j a1 ( j 1)d Recursive definition Closed form, or explicit formula 30 Sum of arithmetic series If a1, a2, …, an is an arithmetic series, then n( a1 an ) ai 2 i 1 n 7/24/2016 31 Geometric series • A geometric series is a sequence of numbers such that the ratio between any two successive members of the sequence is a constant. e.g.: 1, 2, 4, 8, 16, 32 or 10, 20, 40, 80, 160 or 1, ½, ¼, 1/8, 1/16 • In general: a j ra j 1 j 1 Or: 7/24/2016 a j r a0 Recursive definition Closed form, or explicit formula 32 Sum of geometric series (1 r n 1 ) /(1 r ) n n 1 i r ( r 1) /( r 1) i 0 n 1 if r < 1 if r > 1 if r = 1 n 1 2 1 i n 1 n 1 2 2 1 2 2 1 i 0 n n n 1 1 i 1 lim n i lim n ( 2 ) 2 1 12 i 0 2 i 0 n n 1 0 0 lim n i lim n 1 2 1 2 2 1 1 i 1 2 i 0 7/24/2016 33 Important formulas 3 n i 2 ( n 3 ) 3 i 1 n n 1 n (n) i 1 n i i 1 n(n 1) (n 2 ) 2 1 (1) ( r 1) r n ( r ) ( r 1) r 1 i 0 n i r n 1 n k 1 k 1 i ( n ) k 1 i 1 n k n i n 1 n i 2 ( n 1 ) 2 2 ( n 2 ) i 1 n 1 (lg n ) i 1 i n lg i (n lg n) i 1 Remember them, or remember where to find them! 7/24/2016 34 Sum manipulation rules (a b ) a b ca c a i i i i n i i i i i i i x n a a a i m i i m i i x 1 i Example: n n n i 1 i 1 i 1 i i n 1 ( 4 i 2 ) 4 i 2 2 n ( n 1 ) 2 2 n n n 1 n i n i i 1 2 i 1 2 7/24/2016 35 Recursive algorithms • General idea: – Divide a large problem into smaller ones • By a constant ratio • By a constant or some variable – Solve each smaller one recursively or explicitly – Combine the solutions of smaller ones to form a solution for the original problem Divide and Conquer 7/24/2016 36 How to analyze the time-efficiency of a recursive algorithm? • Express the running time on input of size n as a function of the running time on smaller problems 7/24/2016 37 Analyzing merge sort T(n) MERGE-SORT A[1 . . n] Θ(1) 1. If n = 1, done. 2T(n/2) 2. Recursively sort A[ 1 . . n/2 ] and A[ n/2+1 . . n ] . f(n) 3. “Merge” the 2 sorted lists Sloppiness: Should be T( n/2 ) + T( n/2 ) , but it turns out not to matter asymptotically. 7/24/2016 38 Analyzing merge sort 1. Divide: Trivial. 2. Conquer: Recursively sort 2 subarrays. 3. Combine: Merge two sorted subarrays T(n) = 2 T(n/2) + f(n) +Θ(1) # subproblems subproblem size 7/24/2016 1. What is the time for the base case? 2. What is f(n)? 3. What is the growth order of T(n)? Work dividing and Combining Constant 39 Solving recurrence • Running time of many algorithms can be expressed in one of the following two recursive forms T ( n ) aT ( n b) f ( n ) or T ( n ) aT ( n / b) f ( n ) Challenge: how to solve the recurrence to get a closed form, e.g. T(n) = Θ (n2) or T(n) = Θ(nlgn), or at least some bound such as T(n) = O(n2)? 7/24/2016 40 Solving recurrence 1. Recurrence tree (iteration) method - Good for guessing an answer 2. Substitution method - Generic method, rigid, but may be hard 3. Master method - Easy to learn, useful in limited cases only - Some tricks may help in other cases 7/24/2016 41 The master method The master method applies to recurrences of the form T(n) = a T(n/b) + f (n) , where a 1, b > 1, and f is asymptotically positive. 1. Divide the problem into a subproblems, each of size n/b 2. Conquer the subproblems by solving them recursively. 3. Combine subproblem solutions Divide + combine takes f(n) time. 7/24/2016 42 Master theorem T(n) = a T(n/b) + f (n) Key: compare f(n) with nlogba CASE 1: f (n) = O(nlogba – e) T(n) = (nlogba) . CASE 2: f (n) = (nlogba) T(n) = (nlogba log n) . CASE 3: f (n) = (nlogba + e) and a f (n/b) c f (n) T(n) = ( f (n)) . e.g.: merge sort: T(n) = 2 T(n/2) + Θ(n) a = 2, b = 2 nlogba = n CASE 2 T(n) = Θ(n log n) . 7/24/2016 43 Case 1 Compare f (n) with nlogba: f (n) = O(nlogba – e) for some constant e > 0. : f (n) grows polynomially slower than nlogba (by an ne factor). Solution: T(n) = (nlogba) i.e., aT(n/b) dominates e.g. T(n) = 2T(n/2) + 1 T(n) = 4 T(n/2) + n T(n) = 2T(n/2) + log n T(n) = 8T(n/2) + n2 7/24/2016 44 Case 3 Compare f (n) with nlogba: f (n) = (nlogba + e) for some constant e > 0. : f (n) grows polynomially faster than nlogba (by an ne factor). Solution: T(n) = (f(n)) i.e., f(n) dominates e.g. T(n) = T(n/2) + n T(n) = 2 T(n/2) + n2 T(n) = 4T(n/2) + n3 T(n) = 8T(n/2) + n4 7/24/2016 45 Case 2 Compare f (n) with nlogba: f (n) = (nlogba). : f (n) and nlogba grow at similar rate. Solution: T(n) = (nlogba log n) e.g. T(n) = T(n/2) + 1 T(n) = 2 T(n/2) + n T(n) = 4T(n/2) + n2 T(n) = 8T(n/2) + n3 7/24/2016 46 Recursion tree Solve T(n) = 2T(n/2) + dn, where d > 0 is constant. 7/24/2016 47 Recursion tree Solve T(n) = 2T(n/2) + dn, where d > 0 is constant. T(n) 7/24/2016 48 Recursion tree Solve T(n) = 2T(n/2) + dn, where d > 0 is constant. dn T(n/2) 7/24/2016 T(n/2) 49 Recursion tree Solve T(n) = 2T(n/2) + dn, where d > 0 is constant. dn dn/2 T(n/4) 7/24/2016 T(n/4) dn/2 T(n/4) T(n/4) 50 Recursion tree Solve T(n) = 2T(n/2) + dn, where d > 0 is constant. dn dn/2 dn/2 dn/4 dn/4 dn/4 dn/4 (1) 7/24/2016 51 Recursion tree Solve T(n) = 2T(n/2) + dn, where d > 0 is constant. dn dn/2 dn/2 h = log n dn/4 dn/4 dn/4 dn/4 (1) 7/24/2016 52 Recursion tree Solve T(n) = 2T(n/2) + dn, where d > 0 is constant. dn dn dn/2 dn/2 h = log n dn/4 dn/4 dn/4 dn/4 (1) 7/24/2016 53 Recursion tree Solve T(n) = 2T(n/2) + dn, where d > 0 is constant. dn dn dn/2 dn/2 h = log n dn/4 dn/4 dn/4 dn dn/4 (1) 7/24/2016 54 Recursion tree Solve T(n) = 2T(n/2) + dn, where d > 0 is constant. dn dn dn/2 dn/2 dn/4 dn/4 dn/4 dn … h = log n dn/4 dn (1) 7/24/2016 55 Recursion tree Solve T(n) = 2T(n/2) + dn, where d > 0 is constant. dn dn dn/2 dn/2 dn/4 dn/4 dn/4 dn … h = log n dn/4 dn (1) 7/24/2016 #leaves = n (n) 56 Recursion tree Solve T(n) = 2T(n/2) + dn, where d > 0 is constant. dn dn dn/2 dn/2 dn/4 dn/4 dn/4 dn … h = log n dn/4 dn (1) #leaves = n (n) Total (n log n) 7/24/2016 57 Substitution method The most general method to solve a recurrence (prove O and separately): 1. Guess the form of the solution: (e.g. using recursion trees, or expansion) 2. Verify by induction (inductive step). 7/24/2016 58 Proof by substitution • Recurrence: T(n) = 2T(n/2) + n. • Guess: T(n) = O(n log n). (eg. by recurrence tree method) • To prove, have to show T(n) ≤ c n log n for some c > 0 and for all n > n0 • Proof by induction: assume it is true for T(n/2), prove that it is also true for T(n). This means: • Fact: T(n) = 2T(n/2) + n • Assumption: T(n/2)≤ cn/2 log (n/2) • Need to Prove: T(n)≤ c n log (n) 7/24/2016 59 Proof • Fact: T(n) = 2T(n/2) + n • Assumption: T(n/2)≤ cn/2 log (n/2) • Need to Prove: T(n)≤ c n log (n) • Proof: Substitute T(n/2) into the recurrence function => T(n) = 2 T(n/2) + n ≤ cn log (n/2) + n => T(n) ≤ c n log n - c n + n => T(n) ≤ c n log n (if we choose c ≥ 1). 7/24/2016 60 Proof by substitution • Recurrence: T(n) = 2T(n/2) + n. • Guess: T(n) = Ω(n log n). • To prove, have to show T(n) ≥ c n log n for some c > 0 and for all n > n0 • Proof by induction: assume it is true for T(n/2), prove that it is also true for T(n). This means: • Fact: T(n) = 2T(n/2) + n • Assumption:T(n/2) ≥ cn/2 log (n/2) • Need to Prove: T(n) ≥ c n log (n) 7/24/2016 61 Proof • Fact: T(n) = 2T(n/2) + n • Assumption: T(n/2) ≥ cn/2 log (n/2) • Need to Prove: T(n) ≥ c n log (n) • Proof: Substitute T(n/2) into the recurrence function => T(n) = 2 T(n/2) + n ≥ cn log (n/2) + n => T(n) ≥ c n log n - c n + n => T(n) ≥ c n log n (if we choose c ≤ 1). 7/24/2016 62 Quick sort Quicksort an n-element array: 1. Divide: Partition the array into two subarrays around a pivot x such that elements in lower subarray x elements in upper subarray. x x ≥x 2. Conquer: Recursively sort the two subarrays. 3. Combine: Trivial. Key: Linear-time partitioning subroutine. 7/24/2016 63 Partition • All the action takes place in the partition() function – Rearranges the subarray in place – End result: two subarrays • All values in first subarray all values in second – Returns the index of the “pivot” element separating the two subarrays p x 7/24/2016 r q x ≥x 64 Partition Code Partition(A, p, r) x = A[p]; // pivot is the first element i = p; j = r + 1; while (TRUE) { repeat i++; until A[i] > x or i >= j; repeat What is the running time of j--; until A[j] < x or j < i; partition()? if (i < j) Swap (A[i], A[j]); else break; partition() runs in O(n) time } swap (A[p], A[j]); return j; 7/24/2016 65 p x=6 6 r 10 5 8 13 3 2 11 i 6 j 10 5 8 13 3 i 6 2 2 5 8 13 3 2 5 8 13 5 2 5 p 7/24/2016 3 2 5 3 10 11 j 3 13 i 6 10 11 j i 6 11 j i 6 2 8 10 11 j 3 13 j i q 6 13 8 10 11 r 8 10 11 66 6 3 7/24/2016 10 2 5 8 11 3 2 5 6 11 8 13 10 13 2 3 5 6 10 8 11 13 2 3 5 6 8 10 11 13 2 3 5 6 8 10 11 13 67 Quicksort Runtimes • Best case runtime Tbest(n) O(n log n) • Worst case runtime Tworst(n) O(n2) • Worse than mergesort? Why is it called quicksort then? • Its average runtime Tavg(n) O(n log n ) • Better even, the expected runtime of randomized quicksort is O(n log n) 7/24/2016 68 Randomized quicksort • Randomly choose an element as pivot – Every time need to do a partition, throw a die to decide which element to use as the pivot – Each element has 1/n probability to be selected Partition(A, p, r) d = random(); // a random number between 0 and 1 index = p + floor((r-p+1) * d); // p<=index<=r swap(A[p], A[index]); x = A[p]; i = p; j = r + 1; while (TRUE) { … } 7/24/2016 69 Running time of randomized quicksort T(n) = T(0) + T(n–1) + dn T(1) + T(n–2) + dn M T(n–1) + T(0) + dn if 0 : n–1 split, if 1 : n–2 split, if n–1 : 0 split, • The expected running time is an average of all cases Expectation 1 n 1 T ( n ) T ( k ) T ( n k 1) n (n log n ) n k 0 7/24/2016 70 Heaps • In practice, heaps are usually implemented as arrays: 16 14 10 8 2 7 4 3 1 16 14 10 8 7/24/2016 9 7 9 3 2 4 1 71 Heaps • To represent a complete binary tree as an array: – – – – – The root node is A[1] Node i is A[i] The parent of node i is A[i/2] (note: integer divide) The left child of node i is A[2i] The right child of node i is A[2i + 1] 16 14 A = 16 14 10 8 7 9 3 2 4 8 1 = 2 7/24/2016 10 7 4 9 3 1 72 The Heap Property • Heaps also satisfy the heap property: A[Parent(i)] A[i] for all nodes i > 1 – In other words, the value of a node is at most the value of its parent – The value of a node should be greater than or equal to both its left and right children • And all of its descendents – Where is the largest element in a heap stored? 7/24/2016 73 Heap Operations: Heapify() Heapify(A, i) { // precondition: subtrees rooted at l and r are heaps l = Left(i); r = Right(i); if (l <= heap_size(A) && A[l] > A[i]) largest = l; Among A[l], A[i], A[r], else which one is largest? largest = i; if (r <= heap_size(A) && A[r] > A[largest]) largest = r; if (largest != i) { Swap(A, i, largest); If violation, fix it. Heapify(A, largest); } } // postcondition: subtree rooted at i is a heap 7/24/2016 74 Heapify() Example 16 4 10 14 2 7 8 3 1 A = 16 4 10 14 7 7/24/2016 9 9 3 2 8 1 75 Heapify() Example 16 4 10 14 2 7 8 3 1 A = 16 4 10 14 7 7/24/2016 9 9 3 2 8 1 76 Heapify() Example 16 4 10 14 2 7 8 3 1 A = 16 4 10 14 7 7/24/2016 9 9 3 2 8 1 77 Heapify() Example 16 14 10 4 2 7 8 3 1 A = 16 14 10 4 7/24/2016 9 7 9 3 2 8 1 78 Heapify() Example 16 14 10 4 2 7 8 3 1 A = 16 14 10 4 7/24/2016 9 7 9 3 2 8 1 79 Heapify() Example 16 14 10 8 2 7 4 3 1 A = 16 14 10 8 7/24/2016 9 7 9 3 2 4 1 80 Heapify() Example 16 14 10 8 2 7 4 3 1 A = 16 14 10 8 7/24/2016 9 7 9 3 2 4 1 81 Analyzing Heapify(): Formal • T(n) T(2n/3) + (1) • By case 2 of the Master Theorem, T(n) = O(lg n) • Thus, Heapify() takes logarithmic time 7/24/2016 82 Heap Operations: BuildHeap() • We can build a heap in a bottom-up manner by running Heapify() on successive subarrays – Fact: for array of length n, all elements in range A[n/2 + 1 .. n] are heaps (Why?) – So: • Walk backwards through the array from n/2 to 1, calling Heapify() on each node. • Order of processing guarantees that the children of node i are heaps when i is processed 7/24/2016 83 BuildHeap() // given an unsorted array A, make A a heap BuildHeap(A) { heap_size(A) = length(A); for (i = length[A]/2 downto 1) Heapify(A, i); } 7/24/2016 84 BuildHeap() Example • Work through example A = {4, 1, 3, 2, 16, 9, 10, 14, 8, 7} 4 1 3 2 14 7/24/2016 16 8 9 10 7 85 4 1 3 2 14 7/24/2016 16 8 9 10 7 86 4 1 3 14 2 7/24/2016 16 8 9 10 7 87 4 1 10 14 2 7/24/2016 16 8 9 3 7 88 4 16 10 14 2 7/24/2016 7 8 9 3 1 89 16 14 10 8 2 7/24/2016 7 4 9 3 1 90 Analyzing BuildHeap(): Tight • To Heapify() a subtree takes O(h) time where h is the height of the subtree – h = O(lg m), m = # nodes in subtree – The height of most subtrees is small • Fact: an n-element heap has at most n/2h+1 nodes of height h • CLR 7.3 uses this fact to prove that BuildHeap() takes O(n) time 7/24/2016 91 Heapsort Example • Work through example A = {4, 1, 3, 2, 16, 9, 10, 14, 8, 7} 4 1 3 2 14 16 8 A= 7/24/2016 9 10 7 4 1 3 2 16 9 10 14 8 7 92 Heapsort Example • First: build a heap 16 14 10 8 2 7 4 3 1 A = 16 14 10 8 7/24/2016 9 7 9 3 2 4 1 93 Heapsort Example • Swap last and first 1 14 10 8 2 7 4 A= 7/24/2016 9 3 16 1 14 10 8 7 9 3 2 4 16 94 Heapsort Example • Last element sorted 1 14 10 8 2 7 4 A= 7/24/2016 9 3 16 1 14 10 8 7 9 3 2 4 16 95 Heapsort Example • Restore heap on remaining unsorted elements 14 8 10 4 2 7 1 16 A = 14 8 10 4 7/24/2016 9 3 Heapify 7 9 3 2 1 16 96 Heapsort Example • Repeat: swap new last and first 1 8 10 4 2 7 14 A= 7/24/2016 9 3 16 1 8 10 4 7 9 3 2 14 16 97 Heapsort Example • Restore heap 10 8 9 4 2 7 14 3 16 A = 10 8 7/24/2016 1 9 4 7 1 3 2 14 16 98 Heapsort Example • Repeat 9 8 3 4 10 7 14 A= 7/24/2016 1 2 16 9 8 3 4 7 1 2 10 14 16 99 Heapsort Example • Repeat 8 7 3 4 10 2 14 A= 7/24/2016 1 9 16 8 7 3 4 2 1 9 10 14 16 100 Heapsort Example • Repeat 1 2 3 4 10 7 14 A= 7/24/2016 8 9 16 1 2 3 4 7 8 9 10 14 16 101 Analyzing Heapsort • The call to BuildHeap() takes O(n) time • Each of the n - 1 calls to Heapify() takes O(lg n) time • Thus the total time taken by HeapSort() = O(n) + (n - 1) O(lg n) = O(n) + O(n lg n) = O(n lg n) 7/24/2016 102 HeapExtractMax Example 16 14 10 8 2 7 4 3 1 A = 16 14 10 8 7/24/2016 9 7 9 3 2 4 1 103 HeapExtractMax Example Swap first and last, then remove last 1 14 10 8 2 7 4 A= 7/24/2016 9 3 16 1 14 10 8 7 9 3 2 4 16 104 HeapExtractMax Example Heapify 14 8 10 4 2 7 1 3 16 A = 14 8 10 4 7/24/2016 9 7 9 3 2 1 16 105 HeapChangeKey Example Increase key 16 14 10 8 2 7 4 3 1 A = 16 14 10 8 7/24/2016 9 7 9 3 2 4 1 106 HeapChangeKey Example Increase key 16 14 10 15 2 7 4 3 1 A = 16 14 10 15 7 7/24/2016 9 9 3 2 4 1 107 HeapChangeKey Example Increase key 16 15 10 14 2 7 4 3 1 A = 16 15 10 14 7 7/24/2016 9 9 3 2 4 1 108 HeapInsert Example HeapInsert(A, 17) 16 14 10 8 2 7 4 3 1 A = 16 14 10 8 7/24/2016 9 7 9 3 2 4 1 109 HeapInsert Example HeapInsert(A, 17) 16 14 10 8 2 7 4 1 9 3 -∞ -∞ makes it a valid heap A = 16 14 10 8 7/24/2016 7 9 3 2 4 1 -∞ 110 HeapInsert Example HeapInsert(A, 17) 16 14 10 8 2 7 4 1 9 3 17 Now call changeKey A = 16 14 10 8 7/24/2016 7 9 3 2 4 1 17 111 HeapInsert Example HeapInsert(A, 17) 17 16 10 8 2 14 4 1 9 7 A = 17 16 10 8 14 9 7/24/2016 3 3 2 4 1 7 112 • Heapify: Θ(log n) • BuildHeap: Θ(n) • HeapSort: Θ(nlog n) • • • • 7/24/2016 HeapMaximum: Θ(1) HeapExtractMax: Θ(log n) HeapChangeKey: Θ(log n) HeapInsert: Θ(log n) 113 Counting sort 1. for i 1 to k Initialize do C[i] 0 Count 2. for j 1 to n do C[A[ j]] C[A[ j]] + 1 ⊳ C[i] = |{key = i}| Compute running sum 3.for i 2 to k do C[i] C[i] + C[i–1] ⊳ C[i] = |{key i}| 4.for j n downto 1 Re-arrange do B[C[A[ j]]] A[ j] C[A[ j]] C[A[ j]] – 1 7/24/2016 114 Counting sort A: 1 2 3 4 5 4 1 3 4 3 B: 3. for i 2 to k do C[i] C[i] + C[i–1] 7/24/2016 1 2 3 4 C: 1 0 2 2 C': 1 1 3 5 ⊳ C[i] = |{key i}| 115 Loop 4: re-arrange A: B: 1 2 3 4 5 4 1 3 4 3 3 1 2 3 4 C: 1 1 3 5 C': 1 1 3 5 4. for j n downto 1 do B[C[A[ j]]] A[ j] C[A[ j]] C[A[ j]] – 1 7/24/2016 116 Analysis (k) (n) (k) (n) 1. for i 1 to k do C[i] 0 2.for j 1 to n do C[A[ j]] C[A[ j]] + 1 3.for i 2 to k do C[i] C[i] + C[i–1] 4.for j n downto 1 do B[C[A[ j]]] A[ j] C[A[ j]] C[A[ j]] – 1 (n + k) 7/24/2016 117 Stable sorting Counting sort is a stable sort: it preserves the input order among equal elements. A: 4 1 3 4 3 B: 1 3 3 4 4 Why this is important? What other algorithms have this property? 7/24/2016 118 Radix sort • Similar to sorting the address books • Treat each digit as a key • Start from the least significant bit Most significant Least significant 198099109123518183599 340199540380128115295 384700101594539614696 382408360201039258538 614386507628681328936 7/24/2016 119 Time complexity • Sort each of the d digits by counting sort • Total cost: d (n + k) – k = 10 – Total cost: Θ(dn) • Partition the d digits into groups of 3 – Total cost: (n+103)d/3 • We work with binaries rather than decimals – – – – – Partition a binary number into groups of r bits Total cost: (n+2r)d/r Choose r = log n Total cost: dn / log n Compare with dn log n • Catch: faster than quicksort only when n is very large 7/24/2016 120 Randomized selection algorithm RAND-SELECT(A, p, q, i) ⊳ ith smallest of A[ p . . q] if p = q & i > 1 then error! r RAND-PARTITION(A, p, q) kr–p+1 ⊳ k = rank(A[r]) if i = k then return A[ r] if i < k then return RAND-SELECT( A, p, r – 1, i ) else return RAND-SELECT(A, r + 1, q, i – k ) k A[r] A[r] p r q 7/24/2016 121 Example Select the i = 6th smallest: 7 10 pivot Partition: 3 2 5 8 11 3 2 13 k=4 5 7 11 8 10 13 i=6 Select the 6 – 4 = 2nd smallest recursively. 7/24/2016 122 Complete example: select the 6th smallest element. 7 i=6 k=4 3 10 2 5 5 8 7 11 3 2 11 8 10 8 8 10 13 10 13 i=6–4=2 k=3 Note: here we always used first element as pivot to do the partition (instead of rand-partition). 11 13 i=2<k k=2 i=2=k 7/24/2016 10 123 Intuition for analysis (All our analyses today assume that all elements are distinct.) Lucky: T(n) = T(9n/10) + (n) nlog10 / 9 1 n0 1 CASE 3 = (n) Unlucky: arithmetic series T(n) = T(n – 1) + (n) = (n2) Worse than sorting! 7/24/2016 124 Running time of randomized selection T(n) ≤ T(max(0, n–1)) + n T(max(1, n–2)) + n M T(max(n–1, 0)) + n if 0 : n–1 split, if 1 : n–2 split, if n–1 : 0 split, • For upper bound, assume ith element always falls in larger side of partition • The expected running time is an average of all cases Expectation 7/24/2016 1 n 1 T (n ) T max( k , n k 1) n (n ) n k 0 125 Worst-case linear-time selection SELECT(i, n) 1. Divide the n elements into groups of 5. Find the median of each 5-element group by rote. 2. Recursively SELECT the median x of the n/5 group medians to be the pivot. 3. Partition around the pivot x. Let k = rank(x). 4. if i = k then return x elseif i < k then recursively SELECT the ith smallest element in the lower part else recursively SELECT the (i–k)th smallest element in the upper part 7/24/2016 Same as RANDSELECT 126 Developing the recurrence T(n) SELECT(i, n) (n) 1. Divide the n elements into groups of 5. Find the median of each 5-element group by rote. 2. Recursively SELECT the median x of the n/5 group medians to be the pivot. 3. Partition around the pivot x. Let k = rank(x). 4. if i = k then return x elseif i < k then recursively SELECT the ith smallest element in the lower part else recursively SELECT the (i–k)th smallest element in the upper part T(n/5) (n) T(7n/10 +3) 7/24/2016 127 Solving the recurrence 1 7 T (n ) T n T n 3 n 5 10 Assumption: T(k) ck for all k < n T ( n ) c( n 5) c(7n 10 3) n cn 5 3cn / 4 n if n ≥ 60 19cn / 20 n cn ( cn / 20 n ) cn if c ≥ 20 and n ≥ 60 7/24/2016 128 Hash tables U (universe of keys) |U| >> K & |U| >> m k2 0 h(k1) h(k4) k1 k4 K (actual keys) T k5 collision k3 h(k2) = h(k5) h(k3) m-1 • Problem: collision 7/24/2016 129 Chaining • Chaining puts elements that hash to the same slot in a linked list: U (universe of keys) k6 k2 k1 k4 —— k5 k2 —— —— —— k1 k4 K (actual k7 keys) T —— k5 k7 —— —— k8 k3 k3 —— k8 k6 —— —— 7/24/2016 130 Hashing with Chaining • Chained-Hash-Insert (T, x) – Insert x at the head of list T[h(key[x])]. – Worst-case complexity – O(1). • Chained-Hash-Delete (T, x) – Delete x from the list T[h(key[x])]. – Worst-case complexity – proportional to length of list with singly-linked lists. O(1) with doubly-linked lists. • Chained-Hash-Search (T, k) – Search an element with key k in list T[h(k)]. – Worst-case complexity – proportional to length of list. 7/24/2016 131 Analysis of Chaining • Assume simple uniform hashing: each key in table is equally likely to be hashed to any slot • Given n keys and m slots in the table, the load factor = n/m = average # keys per slot • Average cost of an unsuccessful search for a key is (1+) (Theorem 11.1) • Average cost of a successful search is (2 + /2) = (1 + ) (Theorem 11.2) • If the number of keys n is proportional to the number of slots in the table, = n/m = O(1) – The expected cost of searching is constant if is constant 7/24/2016 132 Hash Functions: The Division Method • h(k) = k mod m – In words: hash k into a table with m slots using the slot given by the remainder of k divided by m – Example: m = 31 and k = 78 => h(k) = 16. • Advantage: fast • Disadvantage: value of m is critical – Bad if keys bear relation to m – Or if hash does not depend on all bits of k • Pick m = prime number not too close to power of 2 (or 10) 7/24/2016 133 Hash Functions: The Multiplication Method • For a constant A, 0 < A < 1: • h(k) = m (kA mod 1) = m (kA - kA) Fractional part of kA • • • • • • 7/24/2016 Advantage: Value of m is not critical Disadvantage: relatively slower Choose m = 2P, for easier implementation Choose A not too close to 0 or 1 Knuth: Good choice for A = (5 - 1)/2 Example: m = 1024, k = 123, A 0.6180339887… h(k) = 1024(123 · 0.6180339887 mod 1) = 1024 · 0.018169... = 18. 134 A Universal Hash Function • Choose a prime number p that is larger than all possible keys • Choose table size m ≥ n • Randomly choose two integers a, b, such that 1 a p -1, and 0 b p -1 • ha,b(k) = ((ak+b) mod p) mod m • Example: p = 17, m = 6 h3,4 (8) = ((3*8 + 4) % 17) % 6 = 11 % 6 = 5 • With a random pair of parameters a, b, the chance of a collision between x and y is at most 1/m • Expected search time for any input is (1) 7/24/2016 135 Elements of dynamic programming • Optimal sub-structures – Optimal solutions to the original problem contains optimal solutions to sub-problems • Overlapping sub-problems – Some sub-problems appear in many solutions 7/24/2016 136 Two steps to dynamic programming • Formulate the solution as a recurrence relation of solutions to subproblems. • Specify an order to solve the subproblems so you always have what you need. 7/24/2016 137 Optimal subpaths • Claim: if a path startgoal is optimal, any sub-path, startx, or xgoal, or xy, where x, y is on the optimal path, is also the shortest. • Proof by contradiction – If the subpath between x and y is not the shortest, we can replace it with the shorter one, which will reduce the total length of the new path => the optimal path from start to goal is not the shortest => contradiction! – Hence, the subpath xy must be the shortest among all paths from x to y b start a x y b’ 7/24/2016 a + b + c is shortest c goal b’ < b a + b’ + c < a + b + c 138 Dynamic programming illustration S 0 3 5 3 9 3 5 3 2 6 2 6 13 2 4 17 9 4 5 11 17 11 6 14 2 17 13 13 3 17 2 18 15 3 3 16 4 3 1 3 15 3 7 3 2 2 9 3 6 1 8 13 3 3 2 3 1 3 3 7 12 20 3 2 20 G F(i-1, j) + dist(i-1, j, i, j) F(i, j) = min F(i, j-1) + dist(i, j-1, i, j) 7/24/2016 139 Trace back 0 3 5 9 3 5 3 2 6 2 6 13 2 4 17 9 4 8 11 17 11 6 14 5 17 2 13 2 13 2 17 3 18 16 4 3 1 3 15 3 7 3 15 3 9 3 2 13 3 3 6 1 1 3 2 3 12 3 3 7 7/24/2016 3 20 3 2 20 140 Longest Common Subsequence • Given two sequences x[1 . . m] and y[1 . . n], find a longest subsequence common to them both. “a” not “the” x: A B C B D A y: B D C A B A B BCBA = LCS(x, y) functional notation, but not a function 7/24/2016 141 Optimal substructure • Notice that the LCS problem has optimal substructure: parts of the final solution are solutions of subproblems. – If z = LCS(x, y), then any prefix of z is an LCS of a prefix of x and a prefix of y. i m x z n y j • Subproblems: “find LCS of pairs of prefixes of x and y” 7/24/2016 142 Finding length of LCS m x n y • Let c[i, j] be the length of LCS(x[1..i], y[1..j]) => c[m, n] is the length of LCS(x, y) • If x[m] = y[n] c[m, n] = c[m-1, n-1] + 1 • If x[m] != y[n] c[m, n] = max { c[m-1, n], c[m, n-1] } 7/24/2016 143 DP Algorithm • Key: find out the correct order to solve the sub-problems • Total number of sub-problems: m * n c[i, j] = c[i–1, j–1] + 1 max{c[i–1, j], c[i, j–1]} 0 j if x[i] = y[j], otherwise. n 0 i C(i, j) m 7/24/2016 144 LCS Example (0) j i 0 X[i] 1 A 2 B 3 C 4 B 0 Y[j] 1 B 2 D 3 C 4 A ABCB BDCAB 5 B X = ABCB; m = |X| = 4 Y = BDCAB; n = |Y| = 5 Allocate array c[5,6] 7/24/2016 145 LCS Example (1) j i 0 Y[j] 1 B 2 D 3 C 4 A B 0 0 0 0 0 0 X[i] 0 1 A 0 2 B 0 3 C 0 4 B 0 for i = 1 to m for j = 1 to n 7/24/2016 ABCB BDCAB 5 c[i,0] = 0 c[0,j] = 0 146 LCS Example (2) j i ABCB BDCAB 5 0 Y[j] 1 B 2 D 3 C 4 A B 0 0 0 0 0 X[i] 0 0 1 A 0 0 2 B 0 3 C 0 4 B 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] ) 7/24/2016 147 LCS Example (3) j i ABCB BDCAB 5 0 Y[j] 1 B 2 D 3 C 4 A B 0 0 0 X[i] 0 0 0 0 1 A 0 0 0 0 2 B 0 3 C 0 4 B 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] ) 7/24/2016 148 LCS Example (4) j i ABCB BDCAB 5 0 Y[j] 1 B 2 D 3 C 4 A B 0 0 X[i] 0 0 0 0 0 1 A 0 0 0 0 1 2 B 0 3 C 0 4 B 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] ) 7/24/2016 149 LCS Example (5) j i ABCB BDCAB 5 0 Y[j] 1 B 2 D 3 C 4 A B 0 X[i] 0 0 0 0 0 0 1 A 0 0 0 0 1 1 2 B 0 3 C 0 4 B 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] ) 7/24/2016 150 LCS Example (6) j i ABCB BDCAB 5 0 Y[j] 1 B 2 D 3 C 4 A B 0 X[i] 0 0 0 0 0 0 1 A 0 0 0 0 1 1 2 B 0 1 3 C 0 4 B 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] ) 7/24/2016 151 LCS Example (7) j i ABCB BDCAB 5 0 Y[j] 1 B 2 D 3 C 4 A B 0 X[i] 0 0 0 0 0 0 1 A 0 0 0 0 1 1 2 B 0 1 1 1 1 3 C 0 4 B 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] ) 7/24/2016 152 LCS Example (8) j i ABCB BDCAB 5 0 Y[j] 1 B 2 D 3 C 4 A B 0 X[i] 0 0 0 0 0 0 1 A 0 0 0 0 1 1 2 B 0 1 1 1 1 2 3 C 0 4 B 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] ) 7/24/2016 153 LCS Example (14) j i ABCB BDCAB 5 0 Y[j] 1 B 2 D 3 C 4 A B 0 X[i] 0 0 0 0 0 0 1 A 0 0 0 0 1 1 2 B 0 1 1 1 1 2 3 C 0 1 1 2 2 2 4 B 0 1 1 2 2 3 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] ) 7/24/2016 154 LCS Algorithm Running Time • LCS algorithm calculates the values of each entry of the array c[m,n] • So what is the running time? O(m*n) since each c[i,j] is calculated in constant time, and there are m*n elements in the array 7/24/2016 155 How to find actual LCS • The algorithm just found the length of LCS, but not LCS itself. • How to find the actual LCS? • For each c[i,j] we know how it was acquired: if x[i] y[ j ], c[i 1, j 1] 1 c[i, j ] max( c[i, j 1], c[i 1, j ]) otherwise • A match happens only when the first equation is taken • So we can start from c[m,n] and go backwards, remember x[i] whenever c[i,j] = c[i-1, j-1]+1. 7/24/2016 2 2 2 3 For example, here c[i,j] = c[i-1,j-1] +1 = 2+1=3 156 Finding LCS j 0 Y[j] 1 B 2 D 3 C 4 A 5 B 0 X[i] 0 0 0 0 0 0 1 A 0 0 0 0 1 1 2 B 0 1 1 1 1 2 3 C 0 1 1 2 2 2 4 B 0 1 1 2 2 3 i Time for trace back: O(m+n). 7/24/2016 157 Finding LCS (2) j 0 Y[j] 1 B 2 D 3 C 4 A 5 B 0 X[i] 0 0 0 0 0 0 1 A 0 0 0 0 1 1 2 B 0 1 1 1 1 2 3 C 0 1 1 2 2 2 4 B 0 1 1 2 2 3 i 7/24/2016 LCS (reversed order): B C B LCS (straight order): B C B (this string turned out to be a palindrome) 158 LCS as a longest path problem B D C 7/24/2016 1 1 1 C B B 1 A B A 1 1 159 LCS as a longest path problem B A D C 0 0 0 0 0 0 0 0 1 1 0 1 1 B 0 0 0 1 1 1 1 2 2 2 2 1 1 B C 1 1 B 0 7/24/2016 A 1 1 1 1 1 2 3 160 Restaurant location problem 1 • You work in the fast food business • Your company plans to open up new restaurants in Texas along I-35 • Towns along the highway called t1, t2, …, tn • Restaurants at ti has estimated annual profit pi • No two restaurants can be located within 10 miles of each other due to some regulation • Your boss wants to maximize the total profit • You want a big bonus 7/24/2016 10 mile 161 A DP algorithm • Suppose you’ve already found the optimal solution • It will either include tn or not include tn • Case 1: tn not included in optimal solution – Best solution same as best solution for t1 , …, tn-1 • Case 2: tn included in optimal solution – Best solution is pn + best solution for t1 , …, tj , where j < n is the largest index so that dist(tj, tn) ≥ 10 7/24/2016 162 Recurrence formulation • Let S(i) be the total profit of the optimal solution when the first i towns are considered (not necessarily selected) – S(n) is the optimal solution to the complete problem S(n) = max S(n-1) j < n & dist (tj, tn) ≥ 10 S(j) + pn Generalize S(i) = max S(i-1) j < i & dist (tj, ti) ≥ 10 S(j) + pi Number of sub-problems: n. Boundary condition: S(0) = 0. Dependency: 7/24/2016 S j i-1 i 163 Example Distance (mi) dummy 100 0 Profit (100k) S(i) 5 2 2 6 7 6 3 6 3 6 7 9 8 3 6 7 9 9 10 10 7 4 3 12 2 4 12 5 12 12 14 26 26 Optimal: 26 S(i) = max S(i-1) S(j) + pi j < i & dist (tj, ti) ≥ 10 • Natural greedy 1: 6 + 3 + 4 + 12 = 25 • Natural greedy 2: 12 + 9 + 3 = 24 7/24/2016 164 Complexity • Time: (nk), where k is the maximum number of towns that are within 10 miles to the left of any town – In the worst case, (n2) – Can be improved to (n) with some preprocessing tricks • Memory: Θ(n) 7/24/2016 165 Knapsack problem • Each item has a value and a weight • Objective: maximize value • Constraint: knapsack has a weight limitation Three versions: 0-1 knapsack problem: take each item or leave it Fractional knapsack problem: items are divisible Unbounded knapsack problem: unlimited supplies of each item. Which one is easiest to solve? We study the 0-1 problem today. 7/24/2016 166 Formal definition (0-1 problem) • Knapsack has weight limit W • Items labeled 1, 2, …, n (arbitrarily) • Items have weights w1, w2, …, wn – Assume all weights are integers – For practical reason, only consider wi < W • Items have values v1, v2, …, vn • Objective: find a subset of items, S, such that iS wi W and iS vi is maximal among all such (feasible) subsets 7/24/2016 167 A DP algorithm • Suppose you’ve find the optimal solution S • Case 1: item n is included • Case 2: item n is not included wn Total weight limit: W Find an optimal solution using items 1, 2, …, n-1 with weight limit W - wn 7/24/2016 wn Total weight limit: W Find an optimal solution using items 1, 2, …, n-1 with weight limit W 168 Recursive formulation • Let V[i, w] be the optimal total value when items 1, 2, …, i are considered for a knapsack with weight limit w => V[n, W] is the optimal solution V[n-1, W-wn] + vn V[n, W] = max V[n-1, W] Generalize V[i, w] = V[i-1, w-wi] + vi item i is taken V[i-1, w] item i not taken max V[i-1, w] if wi > w item i not taken Boundary condition: V[i, 0] = 0, V[0, w] = 0. Number of sub-problems = ? 7/24/2016 169 Example • n = 6 (# of items) • W = 10 (weight limit) • Items (weight, value): 2 4 3 5 2 6 7/24/2016 2 3 3 6 4 9 170 w 0 1 2 3 4 5 6 7 8 9 10 0 0 0 0 0 0 0 0 0 0 i wi vi 0 1 2 2 0 2 4 3 0 3 3 3 0 4 5 6 0 5 2 4 0 6 6 9 0 wi V[i-1, w-wi] V[i-1, w] V[i, w] V[i-1, w-wi] + vi item i is taken max V[i, w] = V[i-1, w] V[i-1, w] if wi > w 7/24/2016 item i not taken item i not taken 171 w 0 1 2 3 4 5 6 7 8 9 10 i wi vi 0 0 0 0 0 0 0 0 0 0 0 1 2 2 0 0 2 2 2 2 2 2 2 2 2 2 4 3 0 0 2 2 3 3 5 5 5 5 5 3 3 3 0 0 2 3 3 5 5 6 6 8 8 4 5 6 0 0 2 3 3 6 6 8 9 9 11 5 2 4 0 0 4 4 6 7 7 10 10 12 13 6 6 9 0 0 4 4 6 7 9 10 13 13 15 V[i-1, w-wi] + vi item i is taken max V[i, w] = 7/24/2016 V[i-1, w] V[i-1, w] if wi > w item i not taken item i not taken 172 w 0 1 2 3 4 5 6 7 8 9 10 i wi vi 0 0 0 0 0 0 0 0 0 0 0 1 2 2 0 0 2 2 2 2 2 2 2 2 2 2 4 3 0 0 2 2 3 3 5 5 5 5 5 3 3 3 0 0 2 3 3 5 5 6 6 8 8 4 5 6 0 0 2 3 3 6 6 8 9 9 11 5 2 4 0 0 4 4 6 7 7 10 10 12 13 6 6 9 0 0 4 4 6 7 9 10 13 13 15 Optimal value: 15 Item: 6, 5, 1 Weight: 6 + 2 + 2 = 10 Value: 9 + 4 + 2 = 15 7/24/2016 173 Time complexity • Θ (nW) • Polynomial? – Pseudo-polynomial – Works well if W is small • Consider following items (weight, value): (10, 5), (15, 6), (20, 5), (18, 6) • Weight limit 35 – Optimal solution: item 2, 4 (value = 12). Iterate: 2^4 = 16 subsets – Dynamic programming: fill up a 4 x 35 = 140 table entries • What’s the problem? – Many entries are unused: no such weight combination – Top-down may be better 7/24/2016 174 Longest increasing subsequence • Given a sequence of numbers 125329493568 • Find a longest subsequence that is nondecreasing – E.g. 1 2 5 9 – It has to be a subsequence of the original list – It has to in sorted order => It is a subsequence of the sorted list Original list: 1 2 5 3 2 9 4 9 3 5 6 8 LCS: Sorted: 122334556899 7/24/2016 1234568 175 Events scheduling problem e3 e1 e2 e6 e4 e5 e8 e7 e9 Time • • • A list of events to schedule (or shows to see) – ei has start time si and finishing time fi – Indexed such that fi < fj if i < j Each event has a value vi Schedule to make the largest value – You can attend only one event at any time • Very similar to the new restaurant location problem – Sort events according to their finish time – Consider: if the last event is included or not 7/24/2016 176 Events scheduling problem e3 e1 e2 e6 e4 s8 e8 f8 e7 e5 s7 e9 f7 s9 f9 Time • V(i) is the optimal value that can be achieved when the first i events are considered V(n-1) • V(n) = max { V(j) + vn en not selected en selected j < n and fj < sn 7/24/2016 177 Coin change problem • Given some denomination of coins (e.g., 2, 5, 7, 10), decide if it is possible to make change for a value (e.g, 13), or minimize the number of coins • Version 1: Unlimited number of coins for each denomination – Unbounded knapsack problem • Version 2: Use each denomination at most once – 0-1 Knapsack problem 7/24/2016 178 Use DP algorithm to solve new problems • Directly map a new problem to a known problem • Modify an algorithm for a similar task • Design your own – Think about the problem recursively – Optimal solution to a larger problem can be computed from the optimal solution of one or more subproblems – These sub-problems can be solved in certain manageable order – Works nicely for naturally ordered data such as strings, trees, some special graphs – Trickier for general graphs • The text book has some very good exercises. 7/24/2016 179 Unit-profit restaurant location problem • Now the objective is to maximize the number of new restaurants (subject to the distance constraint) – In other words, we assume that each restaurant makes the same profit, no matter where it is opened 10 mile 7/24/2016 180 A DP Algorithm • Exactly as before, but pi = 1 for all i S(i-1) S(i) = max S(j) + pi j < i & dist (tj, ti) ≥ 10 S(i-1) S(i) = max S(j) + 1 7/24/2016 j < i & dist (tj, ti) ≥ 10 181 Greedy algorithm for restaurant location problem select t1 d = 0; for (i = 2 to n) d = d + dist(ti, ti-1); if (d >= min_dist) select ti d = 0; end end 5 d 7/24/2016 0 2 2 5 7 9 6 6 15 0 3 6 6 9 10 15 0 7 10 0 7 182 Complexity • Time: Θ(n) • Memory: – Θ(n) to store the input – Θ(1) for greedy selection 7/24/2016 183 Optimal substructure • Claim 1: if A = [m1, m2, …, mk] is the optimal solution to the restaurant location problem for a set of towns [t1, …, tn] – m1 < m2 < … < mk are indices of the selected towns – Then B = [m2, m3, …, mk] is the optimal solution to the sub-problem [tj, …, tn], where tj is the first town that are at least 10 miles to the right of tm1 • Proof by contradiction: suppose B is not the optimal solution to the sub-problem, which means there is a better solution B’ to the sub-problem – A’ = mi || B’ gives a better solution than A = mi || B => A is not optimal => contradiction => B is optimal A A’ 7/24/2016 m1 m1 m2 B mk B’ (imaginary) 184 Greedy choice property • Claim 2: for the uniform-profit restaurant location problem, there is an optimal solution that chooses t1 • Proof by contradiction: suppose that no optimal solution can be obtained by choosing t1 – Say the first town chosen by the optimal solution S is ti, i > 1 – Replace ti with t1 will not violate the distance constraint, and the total profit remains the same => S’ is an optimal solution – Contradiction – Therefore claim 2 is valid S S’ 7/24/2016 185 Fractional knapsack problem • Each item has a value and a weight • Objective: maximize value • Constraint: knapsack has a weight limitation 0-1 knapsack problem: take each item or leave it Fractional knapsack problem: items are divisible Unbounded knapsack problem: unlimited supplies of each item. Which one is easiest to solve? We can solve the fractional knapsack problem using greedy algorithm 7/24/2016 186 Greedy algorithm for fractional knapsack problem • Compute value/weight ratio for each item • Sort items by their value/weight ratio into decreasing order – Call the remaining item with the highest ratio the most valuable item (MVI) • Iteratively: – If the weight limit can not be reached by adding MVI • Select MVI – Otherwise select MVI partially until weight limit 7/24/2016 187 Example item Weight (LB) Value ($) $ / LB 1 2 2 1 2 4 3 0.75 3 3 3 1 4 5 6 1.2 5 2 4 2 6 6 9 1.5 7/24/2016 • Weight limit: 10 188 Example item Weight (LB) Value ($) $ / LB 5 2 4 2 6 6 9 1.5 4 5 6 1.2 1 2 2 1 3 3 3 1 2 4 3 0.75 7/24/2016 • Weight limit: 10 • Take item 5 – 2 LB, $4 • Take item 6 – 8 LB, $13 • Take 2 LB of item 4 – 10 LB, 15.4 189 Why is greedy algorithm for fractional knapsack problem valid? • Claim: the optimal solution must contain the MVI as much as possible (either up to the weight limit or until MVI is exhausted) • Proof by contradiction: suppose that the optimal solution does not use all available MVI (i.e., there is still w (w < W) pounds of MVI left while we choose other items) – We can replace w pounds of less valuable items by MVI – The total weight is the same, but with value higher than the “optimal” – Contradiction w w w 7/24/2016 w 190 Graphs • A graph G = (V, E) – V = set of vertices – E = set of edges = subset of V V – Thus |E| = O(|V|2) 1 Vertices: {1, 2, 3, 4} Edges: {(1, 2), (2, 3), (1, 3), (4, 3)} 2 4 3 7/24/2016 191 Graphs: Adjacency Matrix • Example: 1 2 4 3 A 1 2 3 4 1 0 1 1 0 2 0 0 1 0 3 0 0 0 0 4 0 0 1 0 How much storage does the adjacency matrix require? A: O(V2) 7/24/2016 192 Graphs: Adjacency List • Adjacency list: for each vertex v V, store a list of vertices adjacent to v • Example: – – – – Adj[1] = {2,3} Adj[2] = {3} Adj[3] = {} Adj[4] = {3} 1 2 • Variation: can also keep a list of edges coming into vertex 7/24/2016 4 3 193 Kruskal’s algorithm: example c-d: 3 b-f: 5 b-a: 7 b-d: 8 f-g: 9 d-e: 10 a-f: 12 b-c: 14 e-h: 15 7/24/2016 6 6 f-e: a 12 5 b 14 7 8 c 3 f e d 9 15 g h 10 194 Kruskal’s algorithm: example c-d: 3 b-f: 5 b-a: 7 b-d: 8 f-g: 9 d-e: 10 a-f: 12 b-c: 14 e-h: 15 7/24/2016 6 6 f-e: a 12 5 b 14 7 8 c 3 f e d 9 15 g h 10 195 Kruskal’s algorithm: example c-d: 3 b-f: 5 b-a: 7 b-d: 8 f-g: 9 d-e: 10 a-f: 12 b-c: 14 e-h: 15 7/24/2016 6 6 f-e: a 12 5 b 14 7 8 c 3 f e d 9 15 g h 10 196 Kruskal’s algorithm: example c-d: 3 b-f: 5 b-a: 7 b-d: 8 f-g: 9 d-e: 10 a-f: 12 b-c: 14 e-h: 15 7/24/2016 6 6 f-e: a 12 5 b 14 7 8 c 3 f e d 9 15 g h 10 197 Kruskal’s algorithm: example c-d: 3 b-f: 5 b-a: 7 b-d: 8 f-g: 9 d-e: 10 a-f: 12 b-c: 14 e-h: 15 7/24/2016 6 6 f-e: a 12 5 b 14 7 8 c 3 f e d 9 15 g h 10 198 Kruskal’s algorithm: example c-d: 3 b-f: 5 b-a: 7 b-d: 8 f-g: 9 d-e: 10 a-f: 12 b-c: 14 e-h: 15 7/24/2016 6 6 f-e: a 12 5 b 14 7 8 c 3 f e d 9 15 g h 10 199 Kruskal’s algorithm: example c-d: 3 b-f: 5 b-a: 7 b-d: 8 f-g: 9 d-e: 10 a-f: 12 b-c: 14 e-h: 15 7/24/2016 6 6 f-e: a 12 5 b 14 7 8 c 3 f e d 9 15 g h 10 200 Kruskal’s algorithm: example c-d: 3 b-f: 5 b-a: 7 b-d: 8 f-g: 9 d-e: 10 a-f: 12 b-c: 14 e-h: 15 7/24/2016 6 6 f-e: a 12 5 b 14 7 8 c 3 f e d 9 15 g h 10 201 Kruskal’s algorithm: example c-d: 3 b-f: 5 b-a: 7 b-d: 8 f-g: 9 d-e: 10 a-f: 12 b-c: 14 e-h: 15 7/24/2016 6 6 f-e: a 12 5 b 14 7 8 c 3 f e d 9 15 g h 10 202 Kruskal’s algorithm: example c-d: 3 b-f: 5 b-a: 7 b-d: 8 f-g: 9 d-e: 10 a-f: 12 b-c: 14 e-h: 15 7/24/2016 6 6 f-e: a 12 5 b 14 7 8 c 3 f e d 9 15 g h 10 203 Kruskal’s algorithm: example c-d: 3 b-f: 5 b-a: 7 b-d: 8 f-g: 9 d-e: 10 a-f: 12 b-c: 14 e-h: 15 7/24/2016 6 6 f-e: a 12 5 b 14 7 8 c 3 f e d 9 15 g h 10 204 Time complexity • Depending on implementation • Pseudocode: sort all edges according to weights Θ(m log m) T = {}. tree(v) = v for all v. = Θ(m log n) m edges for each edge (u, v) Avg time spent per edge if tree(u) != tree(v) Naïve: Θ (n) T = T U (u, v); Better: Θ (log n) union (tree(u), tree(v)) using set union Overall time complexity Naïve: Θ(nm) Better implementation: Θ(m log n) 7/24/2016 205 Prim’s algorithm: example a 6 5 b 14 3 7/24/2016 b ∞ ∞ f 7 8 c a 12 e 9 15 g h 10 d c d e f g h ∞ ∞ ∞ ∞ ∞ ∞ 206 Prim’s algorithm: example a 6 12 5 b 14 f 7 8 c 3 e 9 15 g h 10 d ChangeKey 7/24/2016 c b a d e f g h 0 ∞ ∞ ∞ ∞ ∞ ∞ ∞ 207 Prim’s algorithm: example a 6 12 5 b 14 f 7 8 c 3 e 9 15 g h 10 d ExctractMin 7/24/2016 h b a d e f g ∞ ∞ ∞ ∞ ∞ ∞ ∞ 208 Prim’s algorithm: example a 6 12 5 b 14 f 7 8 c 3 e 9 15 g h 10 d ChangeKey 7/24/2016 d b a h e f g 3 14 ∞ ∞ ∞ ∞ ∞ 209 Prim’s algorithm: example a 6 12 5 b 14 f 7 8 c 3 e 9 15 g h 10 d ExctractMin b 7/24/2016 g a h e f 14 ∞ ∞ ∞ ∞ ∞ 210 Prim’s algorithm: example a 6 12 5 b 14 f 7 8 c 3 e d 9 15 g h 10 Changekey 7/24/2016 b e a h g f 8 10 ∞ ∞ ∞ ∞ 211 Prim’s algorithm: example a 6 12 5 b 14 f 7 8 c 3 e d 9 15 g h 10 ExtractMin e 7/24/2016 f 10 ∞ a h g ∞ ∞ ∞ 212 Prim’s algorithm: example a 6 12 5 b 14 f 7 8 c 3 e 9 15 g h 10 d Changekey 7/24/2016 f e a h g 5 10 6 ∞ ∞ 213 Prim’s algorithm: example a 6 5 b 14 f 7 8 c 3 e 9 15 g h 10 d ExtractMin 7/24/2016 12 a e g h 6 10 ∞ ∞ 214 Prim’s algorithm: example a 6 12 5 b 14 f 7 8 c 3 e 9 15 g h 10 d Changekey 7/24/2016 a e g h 6 7 9 ∞ 215 Prim’s algorithm: example a 6 12 5 b 14 7 8 c 3 f e d 9 15 g h 10 ExtractMin 7/24/2016 e h g 7 ∞ 9 216 Prim’s algorithm: example a 6 12 5 b 14 7 8 c 3 f e d 9 15 g h 10 ExtractMin 7/24/2016 g h 9 ∞ 217 Prim’s algorithm: example a 6 12 5 b 14 7 8 c 3 f e d 9 15 g h 10 Changekey 7/24/2016 g h 9 15 218 Prim’s algorithm: example a 6 12 5 b 14 7 8 c 3 f e d 9 15 g h 10 ExtractMin h 7/24/2016 15 219 Prim’s algorithm: example a 6 5 b 14 3 f 7 8 c 7/24/2016 12 e d 9 15 g h 10 220 Complete Prim’s Algorithm MST-Prim(G, w, r) Q = V[G]; for each u Q Overall running time: Θ(m log n) key[u] = ; key[r] = 0; Cost per ChangeKey T = {}; n vertices while (Q not empty) u = ExtractMin(Q); Θ(n) times for each v Adj[u] if (v Q and w(u,v) < key[v]) T = T U (u, v); ChangeKey(v, w(u,v)); Θ(n2) times? How often is ExtractMin() called? How often is ChangeKey() called? 7/24/2016 Θ(m) times 221 Summary • Kruskal’s algorithm – Θ(m log n) – Possibly Θ(m + n log n) with counting sort • Prim’s algorithm – With priority queue : Θ(m log n) • Assume graph represented by adj list – With distance array : Θ(n^2) • Adj list or adj matrix – For sparse graphs priority queue wins – For dense graphs distance array may be better 7/24/2016 222 14 b 9 14 h f 7 1 6 7 9 3 5 5 e d 6 8 0 a i 4 7 2 1 c 7 g 7/24/2016 a b c d e f g h i ∞ 14 7 5 0 ∞ ∞ ∞ ∞ Dijkstra’s algorithm 223 14 11 b 9 14 h f 7 1 6 7 9 3 5 5 e d 6 8 0 a i 4 11 7 2 1 c 7 g a 7/24/2016 b c d e f g h i 11 11 7 5 0 ∞ ∞ ∞ ∞ Dijkstra’s algorithm 224 14 11 b 9 14 h f 7 1 6 7 9 3 5 a 1 11 9 i 5 e d 6 8 0 4 7 2 c 7 g 7/24/2016 a b c d e f g h i 9 11 7 5 0 ∞ ∞ ∞ ∞ Dijkstra’s algorithm 225 14 11 b 9 14 12 h f 7 1 6 7 9 3 5 17 a 1 11 9 i 5 e d 6 8 0 4 7 2 c 7 g 7/24/2016 a b c d e f g h i 9 11 7 5 0 12 ∞ ∞ 17 Dijkstra’s algorithm 226 9 20 14 11 b 14 12 h f 7 1 6 7 9 3 5 17 a 1 11 9 i 5 e d 6 8 0 4 7 2 c 7 g 7/24/2016 a b c d e f g h 9 11 7 5 0 12 ∞ 20 17 Dijkstra’s algorithm i 227 9 20 19 14 11 b 14 12 h f 7 1 6 7 9 3 5 17 a 1 11 9 i 5 e d 6 8 0 4 7 2 c 7 g 7/24/2016 a b c d e f g h 9 11 7 5 0 12 ∞ 19 17 Dijkstra’s algorithm i 228 9 20 19 18 14 11 b 14 12 h f 7 1 6 7 9 3 5 17 a 1 11 9 i 4 7/24/2016 e 7 2 c g 5 d 6 8 0 7 18 a b c d e 9 11 7 5 0 f g h i 12 18 18 17 Dijkstra’s algorithm 229 9 20 19 18 14 11 b 14 12 h f 7 1 6 7 9 3 5 17 a 1 11 9 i 4 7/24/2016 e 7 2 c g 5 d 6 8 0 7 18 a b c d e 9 11 7 5 0 f g h i 12 18 18 17 Dijkstra’s algorithm 230 9 20 19 18 14 11 b 14 12 h f 7 1 6 7 9 3 5 17 a 1 11 9 i 4 7/24/2016 e 7 2 c g 5 d 6 8 0 7 18 a b c d e 9 11 7 5 0 f g h i 12 18 18 17 Dijkstra’s algorithm 231 Prim’s Algorithm MST-Prim(G, w, r) Q = V[G]; for each u Q Overall running time: Θ(m log n) key[u] = ; key[r] = 0; Cost per ChangeKey T = {}; while (Q not empty) u = ExtractMin(Q); for each v Adj[u] if (v Q and w(u,v) < key[v]) T = T U (u, v); ChangeKey(v, w(u,v)); 7/24/2016 232 Dijkstra’s Algorithm Dijkstra(G, w, r) Q = V[G]; for each u Q Overall running time: Θ(m log n) key[u] = ; key[r] = 0; Cost per ChangeKey T = {}; while (Q not empty) u = ExtractMin(Q); for each v Adj[u] if (v Q and key[u]+w(u,v) < key[v]) T = T U (u, v); ChangeKey(v, key[u]+w(u,v)); Running time of Dijkstra’s algorithm is the same as Prim’s algorithm 7/24/2016 233 Good luck with your final! 7/24/2016 234