What is divide-and-conquer? An example problem: eat some cake Description: given some amount of cake, eat all of them When the cake is like:
What is divide-and-conquer? When the cake is like…. Hint: you need not to eat all of them at the first time
What is divide-and-conquer? Any ideas? Case 1: a small piece of cake – Eat all of them Case 2: a lot of cake – Cut off a small piece – and EatAllTheCake( the small piece) – Put the rest into a refrigerator – 24 housrs later, EatAllTheCake( the rest of the cake ) Base case Recursive case Solve a smaller problem Do some other things Smaller input size
What is divide-and-conquer? Textbook definition: – Divide the problem into a number of subproblems that are smaller instances of the same problem – Conquer the subproblems by solving them recursively. If the subproblem sizes are small enough, however, just solve the subproblems in a straight forward manner. – Combine the solutions to the subproblems into the solution for the original problem
Pros and cons Pros: – Many problems can be solved by a straightforward divide-and-conquer algorithm Cons: – Time complexity is not always good
An example: calculate factorial of n Problem: calculate n! What is n!? What is the iterative algorithm? fact1(n) – f=1; – for i = n to 1 – f = f * i; – return f;
An example: calculate the factorial of n What is the divide-and-conquer algorithm? fact2(n) – if(n<=1) return 1; – return n*fact2(n-1); Recursive case Base case Smaller problem Combination Lets try it in Java
Tail recursion What happen when fact2(5)? fact2(5) n <- 5; m = fact2(4); n*m; fact2(4) n <- 4; m = fact2(3); n*m; fact2(3) n <- 3; m = fact2(2); n*m; fact2(2) n <- 2; m = fact2(1); n*m; fact2(1) return 1; For each call, there is some storage used to save the current state Can we save those space? fact2(n) if(n<=1) return 1; return n*fact2(n-1);
Tail recursion Tail recursion: there is only one self call, and it is the last operation. E.g.: fact3(n, currentFactotial) – if(n<=1) return currentFactotial; – return fact3(n-1, currentFactotial*n); What is the first call? – fact3(n, 1); What happened in fact3?
Tail recursion What happen when fact3(5)? fact3(5, currentFactotial) m <- currentFactotial*5; fact3(4,m ); With a tail recursion, local variable need not to be saved fact3(4, currentFactotial) m <- currentFactotial*4; fact3(3,m ); fact3(3, currentFactotial) m <- currentFactotial*3; fact3(2,m ); fact3(2, currentFactotial) m <- currentFactotial*2; fact3(1,m ); fact3(1, currentFactotial) return currentFactotial; fact3(n, currentFactotial) if(n<=1) return currentFactotial; return fact3(n-1, currentFactotial*n); Lets improve the code
More exercises-print all strings Problem: – Each character could be: a, b, c, d or e. – Print all the possible n character strings printAllStrings( int n, string head) – if(n==0) print head; – else printAllStrings(n-1, head+a);
More exercises – tower of Hanoi Tower of Hanoi: move all disks to the third rod Only one disk may be moved at a time. No disk may be placed on top of a smaller disk.
More exercises – tower of Hanoi What is the algorithm to solve tower of Hanoi problem? Hanoi( number of disks n, current rod c, destination rod d, auxiliary rod a ) – if(n==0) //nothing – else Move top n-1 disks to auxiliary rod: Hanoi(n-1, c, a, d) Move the last disk to destination rod Move the n-1 disks from auxiliary rod to destination rod: Hanoi(n-1, a, d, c) Lets try it in Java
More exercises Have you seen other algorithms? – Quicksort – Mergesort – Heapify – Heapsort ….
Analysis of divide-and-conquer algorithms Recurrence Solve recurrence