3 DaC
3 DaC
FUNCTIONS
Problem
divide
Smaller Smaller
Problem Problem
divide
Smaller Smaller
Problem Problem
conquer
Sub
Solution
……………………
conquer
Solution
[Link]
1
DIVIDE AND CONQUER
Algorithm design paradigm based on multi-branched recursion.
A divide and conquer algorithm works by recursively breaking down a problem
into two or more sub-problems of the same or related type, until these become
simple enough to be solved directly.
The solutions to the sub-problems are then combined to give a solution to the
original problem.
3
GETTING THE RECURRENCE RELATION
int expo(int x, int n){ //T(n) int fibo (int n) { #define ll long long int
if (n==0) return 1; //T(0)=1 if (n<2) return 1; ll sum(int n)
int p=expo(x,n/2);//T(n/2) // BASE CONDITION {
if (n%2) /* n is odd */ return fibo (n-1) if (n == 1) return 1;
return x*p*p; +fibo(n-2); else // Recursive call
return p*p; } return
} // T(n)=T(n-1)+T(n-2) (ll) n*n + sum(n - 1)); }
// T(n)=T(n/2)+O(1) // T(0)=T(1)=1 // T(n)=T(n-1)+c
// T(0)=1 // T(1)=T(1)
MergeSort(ary) //T(n)
bool isSorted(int *a, int n) {
{ if (n==1) return;
if (n == 1) return true;
ary_start = MergeSort(ary[0:n/2]); //T(n/2)
if (a[n-2] > a[n-1]) return false;
ary_end = MergeSort(ary[n/2:n]); //T(n/2)
else return isSorted(a, n-1);
return MergeArrays(ary_start, ary_end); //O(n)
}
}
// T(n)=T(n-1)+1, T(0)=1
// T(n)=2T(n/2)+O(n) , T(1)=1
4
TOWER OF HANOI
1. Only one disk can be moved at a time.
2. Each move consists of taking the upper disk from one of the stacks and
placing it on top of another stack i.e. a disk can only be moved if it is the
uppermost disk on a stack.
3. No disk may be placed on top of a smaller disk.
Solution: Label the pegs A, B, C, let n be the total number of discs
number the discs from 1 (smallest, topmost) to n (largest, bottommost)
To move n discs from peg A to peg C:
• move n−1 discs from A to B. This leaves disc n alone on peg A
• move disc n from A to C
• move n−1 discs from B to C so they
sit on disc n
5
TOWER OF HANOI AND RECURSION
void Hanoi (int n, char source, char dest, char aux){
//Base condition
if (n==1) printf("Move a disc from Peg %c TO %c\n",source,dest);
else {
Hanoi(n-1,source,aux,dest);
Hanoi(1,source,dest,-1);
Hanoi(n-1,aux,dest,source); Move a disc from Peg a TO b
Move a disc from Peg a TO c
} Move a disc from Peg b TO c
} Move a disc from Peg a TO b
int main(){ Move a disc from Peg c TO a
Hanoi(3,'a','b','c'); Move a disc from Peg c TO b
} Move a disc from Peg a TO b
6
TOWER OF HANOI AND RECURSION Assume Time
Complexity T(n)
void Hanoi (int n, char source, char dest, char aux){
//Base condition T(1) = Or O(1) constant
if (n==1) printf("Move a disc from Peg %c TO %c\n",source,dest);
else { T(n-1)
Hanoi(n-1,source,aux,dest); +
Hanoi(1,source,dest,-1); constant
Hanoi(n-1,aux,dest,source);
} +
T(n-1)
}
int main(){
Hanoi(3,'a','b','c');
}
T (n) 2T (n 1) 1, T (1) 1
7
MERGE SORT
void mergeSort(int n) // +ARRAY[n] // T(n)=
{
if () // BASE CONDITION
h1=mergeSort(n/2); Sort first half // T(n/2) +
h2=mergeSort(n/2); Sort second half // T(n/2) +
merge(h1,h2); // O(n)
}
// T(n) = 2T(n/2) +O(n),
8
MERGESORT EXAMPLE 8 3 2 9 7 1 5 4
8 3 2 9 7 1 5 4
Merge((8),(3))->(3,8)
Merge((2),(9))->(2,9) 3 8 2 9 1 7 4 5
…
2 3 8 9 1 4 5 7
Merge((3,8),(2,9)->(2,3,8,9)
… 1 2 3 4 5 7 8 9
9
def mergeSort(myList): #Recursive : T(n),
if len(myList) > 1: #T(0)=c
mid = len(myList) // 2
MERGESORT IN PYTHON
left = myList[:mid]
right = myList[mid:]
# Recursive call on each half 2*T(n/2)
mergeSort(left)
mergeSort(right)
i,j,k= 0,0,0
#### O(n)
while i < len(left) and j < len(right): Before [6, 2, 9, 5]
if left[i] < right[j]: myList[k] = left[i];i += 1 After [2, 5, 6, 9]
else: myList[k] = right[j]; j += 1 Before [100,14,119,26,127,31,133,35, 142,44]
k += 1
After [14,26,31,35,44,100,119,127,133,142]
while i < len(left): myList[k] = left[i];i += 1;k += 1
while j < len(right): myList[k]=right[j];j += 1;k += 1
myList = [6,2,9,5];print("Before",myList);
mergeSort(myList);print('After',myList)
myList=[100,14,119,26,127,31,133,35,142,44]
print("Before",myList);mergeSort(myList);print('After',myList)
10
def mergeSort(a): #Iterative
current_size = 1
while current_size <= len(a) - 1:
MERGESORT IN PYTHON
left = 0
while left < len(a)-1:
mid = min((left + current_size - 1),(len(a)-1))
right =min(len(a)-1,2 * current_size + left - 1)
merge(a, left, mid, right)
left += current_size*2
current_size *= 2
def merge(a, l, m, r): #left from l to m, right from m+1 to r SO:
n1 = m - l + 1;n2 = r - m
L=a[l:m+1];R=a[m+1:r+1]
i, j, k = 0, 0, l
while i < n1 and j < n2: #Do Merge a=[8,3,2,9,7,1,5,4]
if L[i] > R[j]:a[k] = R[j];j += 1 print("Before:",a)
else: a[k] = L[i];i += 1 mergeSort(a)
k += 1
print("After :",a)
while i < n1: a[k] = L[i];i += 1;k += 1 #Remaining parts
while j < n2: a[k] = R[j];j += 1;k += 1 #Remaining parts Before: [8, 3, 2, 9, 7, 1, 5, 4]
After : [1, 2, 3, 4, 5, 7, 8, 9]
11
MERGESORT() - C
#include <stdio.h>
#define max 10
int a[10] = { 100,14,119,26,127,31,133,35, 142, 44 };
int b[10];// Bad Global Arrays ! void sort(int low, int high) {
void merging(int low, int mid, int high) { int mid;
int l1, l2, i;
for(l1 = low, l2 = mid + 1, i = low; if(low < high) {
l1 <= mid && l2 <= high; i++) {
if(a[l1] <= a[l2]) mid = (low + high) / 2;
b[i] = a[l1++]; sort(low, mid);
else sort(mid+1, high);
b[i] = a[l2++]; merging(low, mid, high);
} } else {
while(l1 <= mid) b[i++] = a[l1++];
while(l2 <= high) b[i++] = a[l2++]; return;
for(i = low; i <= high; i++) }
a[i] = b[i]; }
}
12
SOLVING A RECURRENT RELATION
1: SUBSTITUTION METHOD
• Guess the Solution.
• Use the mathematical induction method
13
SOLVING A RECURRENT RELATION
2: ITERATION METHOD Tower of Hanoi
15
SOLVING A RECURRENT RELATION T ( n) 3T ( n / 2) n;T( 1 ) 1
2: ITERATION METHOD (TELESCOPING) [T(n/ 2 ) 3T(n/ 4 ) cn/ 2 ]
n
T ( n) 2T ( n / 2) cn 3 T( 1 ) 32 T( 2n2 ) n * 3 / 2
1
2
[T(n/ 2 ) 2T(n/ 4 ) cn/ 2 ] n
32 T( 2 ) 33 T( 2n3 ) n * (3 / 2) 2
n 2
2 T( 1 ) 2 2 T( 2n2 ) cn
1 ..........
2 n
3d 1T( d 1 ) 3d T( 2nd ) n * (3 / 2) d 1
n 2
2 2 T( 2 ) 23 T( 2n3 ) cn n
Merge Sort
2 3 T( d ) 3 T( 1 ) 3 O( 1 ) n log 2 3O (1)
d d log n2
2
..........
log 2 ( n )
d 1 n n[ 3 1]
2 T( d 1
) 2 d T( n
2d
) cn n(3 / 2) i 2
2 i 0 , log 2 n 1
3 1
n 2
2 d T( d ) 2 d T( 1 ) 2 log 2 O( 1 ) cn
n log 2 ( n )
2n( 3 1) 2n( n log 2 ( 3 / 2 ) 1)
2 2
log 2 3 log 2 2
2n( n 1) 2n( n log 2 3 / n 1)
Erat
Quod Demonstrandum
T ( n) O ( n log 2 3 n) ( n log 2 3 ) ( n log 2 3 )
T ( n) dcn cn O ( n log(n) n) Q.E.D
16
SOLVING A RECURRENT RELATION d depth log b n
n
T ( n) ( n log b a
a f ( i ))
i
17 i 0 , d 1 b
ab2
SOLVING A RECURRENT RELATION depth log 2 n
3: RECURRENCE TREE # leaves 2 depth 2 log 2 n
# leaves n log 2 2 n
T(N)=2T(n/2)+1, T(1)=1 Tn
Tn/2 1 Tn/2 1
af(n/b)=2
Tn/4 1 Tn/4 Tn/4 1 Tn/4 2
2d
sum=2d =n
18
ab2
SOLVING A RECURRENT RELATION depth log 2 n
3: RECURRENCE TREE # leaves 2 depth 2 log 2 n
# leaves n log 2 2 n
Merge Sort: T(N)=2T(n/2)+n,T(1)=1
Tn
Tn/2 n Tn/2 n
2(n/2)
Tn/4 n/2 Tn/4 Tn/4 n/2 Tn/4 n
4(n/4)
Tn/8 n/4 Tn/8 Tn/8 n/4 Tn/8 Tn/8 n/4 Tn/8 Tn/8 n/4 Tn/8 n d
sum=
n*d=
n*log(n)
(1) (1) (1) (1) T(n) θ(n n log 2 n) θ(n log 2 n) (1) (1) (1) (1)
2d
sum=2d = 2log(n) = n
19
SOLVING A RECURRENT RELATION
4: MASTER THEOREM
Let c crit log b a
1. If f(n) O(n crit - ) then T(n) (n crit )
2. If f(n) (n crit log k n) where k 0 then T(n) (n crit log kb 1n)
[Link] f(n) (n crit ) then T(n) (f(n))
c1) for cases 1,3 : ε is a constant such that ε 0.
c2) for case 3 : (regularity condition) There must exist a constant
c 1 such that af(n/b) cf(n) for large n.
20
MASTER METHOD, EXAMPLE 1
Example (Binary search): T (n) T (n / 2) 1
Let c crit log b a
1. If f(n) O(n crit - ) then T(n) (n crit )
2. If f(n) (n crit log k n) where k 0 then T(n) (n crit log kb 1n)
[Link] f(n) (n crit ) then T(n) (f(n))
c1) for cases 1,3 : ε is a constant such that ε 0.
c2) for case 3 : (regularity condition) There must exist a constant
c 1 such that af(n/b) cf(n) for large n.
a=1,b=2
Solution:c crit log b a 0
Case 2: with k=0, hence T(n) is ( log2 n).
21
MASTER METHOD, EXAMPLE 2
Example: T (n) 2T (n / 2) n log n
Let c crit log b a
1. If f(n) O(n crit - ) then T(n) (n crit )
2. If f(n) (n crit log k n) where k 0 then T(n) (n crit log kb 1n)
[Link] f(n) (n crit ) then T(n) (f(n))
c1) for cases 1,3 : ε is a constant such that ε 0.
c2) for case 3 : (regularity condition) There must exist a constant
c 1 such that af(n/b) cf(n) for large n.
a=b=2
Solution:c crit log b a 1
Case 2: with k=1, hence T(n) is (n log2 n).
22
MASTER METHOD, EXAMPLE 3
Example: T (n) T (n / 3) n log n
Let c crit log b a
1. If f(n) O(n crit - ) then T(n) (n crit )
2. If f(n) (n crit log k n) where k 0 then T(n) (n crit log kb 1n)
[Link] f(n) (n crit ) then T(n) (f(n))
c1) for cases 1,3 : ε is a constant such that ε 0.
c2) for case 3 : (regularity condition) There must exist a constant
c 1 such that af(n/b) cf(n) for large n.
a=4,b=2
27
MASTER METHOD, EXAMPLE 6
Example: T (n) 4T (n / 2) n
Let c crit log b a
1. If f(n) O(n crit - ) then T(n) (n crit )
2. If f(n) (n crit log k n) where k 0 then T(n) (n crit log kb 1n)
[Link] f(n) (n crit ) then T(n) (f(n))
c1) for cases 1,3 : ε is a constant such that ε 0.
c2) for case 3 : (regularity condition) There must exist a constant
c 1 such that af(n/b) cf(n) for large n.
31
MASTER METHOD, GAP EXAMPLE 9
Example:T ( n) 2T ( n / 2) n log(n);T( 1 ) 1
Let c crit log b a
1. If f(n) O(n crit - ) then T(n) (n crit )
2. If f(n) (n crit log k n) where k 0 then T(n) (n crit log kb 1n)
[Link] f(n) (n crit ) then T(n) (f(n))
c1) for cases 1,3 : ε is a constant such that ε 0.
c2) for case 3 : (regularity condition) There must exist a constant
c 1 such that af(n/b) cf(n) for large n.
c1) f(n)/ncrit=log(n)
a=2,b=2 >O(n)
Solution: c crit log 2 2 1 f(n) is asymptotically
Case 3: wrong larger ,but not
32
polynomially larger
MASTER METHOD, EXAMPLE 10
Example: T (n) 3T (n / 4) nlog (n)
Let c crit log b a
1. If f(n) O(n crit - ) then T(n) (n crit )
2. If f(n) (n crit log k n) where k 0 then T(n) (n crit log kb 1n)
[Link] f(n) (n crit ) then T(n) (f(n))
c1) for cases 1,3 : ε is a constant such that ε 0.
c2) for case 3 : (regularity condition) There must exist a constant
c 1 such that af(n/b) cf(n) for large n.
a=3,b=4
33
MASTER METHOD, EXAMPLE 10
Example: T (n) 3T (n / 4) nlog (n)
Let c crit log b a
1. If f(n) O(n crit - ) then T(n) (n crit )
2. If f(n) (n crit log k n) where k 0 then T(n) (n crit log kb 1n)
[Link] f(n) (n crit ) then T(n) (f(n))
c1) for cases 1,3 : ε is a constant such that ε 0.
c2) for case 3 : (regularity condition) There must exist a constant
c 1 such that af(n/b) cf(n) for large n.
c1) f(n)/ncrit=n0.2log(n)
a=3,b=4
=(n+) or: > n
Solution:c crit log b a 0.793
c2) 3(n/4)log(n/4)
Case 3: hence T(n) is (n log(n))
≤(3/4)n log n=cf(n)
34
EXAMPLE 1: NAÏVE MATRIX MULTIPLY
//implementation C = A*B
for i = 1 to n C(i,j) C(i,j) A(i,:)
for j = 1 to n = + B(:,j)
*
for k = 1 to n
C(i,j) = C(i,j) + A(i,k) * B(k,j)
EXAMPLE 1: DAC
A B = R
•Divide matrices into sub-
matrices: A0 , A1, A2 etc
A0 A1 B0 B1 A0B0+A1B2 A0B1+A1B3
=
•Use blocked matrix
multiply equations
A2 A3 B2 B3 A2B0+A3B2 A2B1+A3B3 •Recursively multiply sub-
matrices
35
EXAMPLE 1: DIVIDE AND CONQUER MATRIX MULTIPLY
A B = C
A0 A1 B0 B1 A0B0+A1B2 A0B1+A1B3
=
A2 A3 B2 B3 A2B0+A3B2 A2B1+A3B3
T (n) 8T (n / 2) n , T (1) 1
2
T ( n) n log2 8
T ( n) n 3
P1 = (A11+ A22)(B11+B22)
P2 = (A21 + A22) * B11
C11 = P1 + P4 - P5 + P7
P3 = A11 * (B12 - B22)
C12 = P3 + P5
P4 = A22 * (B21 - B11)
C21 = P2 + P4 T ( n) 7 T (n / 2) n 2 , T (1) 1
P5 = (A11 + A12) * B22
C22 = P1 + P3 - P2 + P6
P6 = (A21 - A11) * (B11 + B12)
P7 = (A12 - A22) * (B21 + B22)
a 7; b 2; d 2; a b ; so 2
T ( n ) ( n log b a
) ( n log 2 7
)
T (n) (n 2.58 )
37
EXAMPLE 2: QUICKSORT
Efficient sorting algorithm
Discovered by C.A.R. Hoare
Example of Divide and Conquer algorithm
Two phases
Partition phase
Divides the work into half < pivot pivot > pivot
Choose a pivot
Find the position for the pivot so that
all elements to the left are less
all elements to the right are greater
< pivot > pivot
}
}
39
QUICKSORT - PARTITION
int partition( int *a, int low, int high ) {
int left, right;
int pivot_item;
pivot_item = a[low];
pivot = left = low;
right = high;
while ( left < right ) {
/* Move left while item < pivot */
while( a[left] <= pivot_item ) left++;
/* Move right while item > pivot */
while( a[right] >= pivot_item ) right--;
if ( left < right ) SWAP(a,left,right);
}
/* right is final position for the pivot */
a[low] = a[right];
a[right] = pivot_item;
return right;
}
40
QUICKSORT - PARTITION
int partition( int *a, int low, int high ) {
This example
uses int’s
int left, right; to keep things
int pivot_item; simple!
pivot_item = a[low];
pivot = left = low;
right = high; Any item will do as the pivot,
while ( left < right ) { choose the leftmost one!
/* Move left while item < pivot */
while( a[left] <= pivot_item ) left++;
/* Move right while item > pivot */
while( a[right] >= pivot_item ) right--;
if ( left < right ) SWAP(a,left,right);
}
23 12 15 38 42 18 36 29 27
/* right is final position for the pivot */
a[low] = a[right];
a[right] = pivot_item;
return right;
} low high
41
QUICKSORT - PARTITION
int partition( int *a, int low, int high ) {
int left, right;
int pivot_item;
pivot_item = a[low];
pivot = left = low; Set left and right markers
right = high;
while ( left < right ) {
/* Move left while item < pivot */
while(
left a[left] <= pivot_item ) left++;right
/* Move right while item > pivot */
while( a[right] >= pivot_item ) right--;
if (23left12 < right
15 38) SWAP(a,left,right);
42 18 36 29 27
}
/* right is final position for the pivot */
a[low] = a[right];
low pivot: 23 high
a[right] = pivot_item;
return right;
}
42
QUICKSORT - PARTITION
int partition( int *a, int low, int high ) {
int left, right;
int pivot_item;
pivot_item = a[low];
pivot = left = low; Move the markers
right = high; until they cross over
while ( left < right ) {
/* Move left while item < pivot */
while( a[left] <= pivot_item ) left++;
/* Move right while item > pivot */
while( a[right] >= pivot_item ) right--;
if ( left < right ) SWAP(a,left,right);
} left right
/* right is final position for the pivot */
a[low] = a[right];
23 12 15 38 42 18 36 29 27
a[right] = pivot_item;
return right;
} low pivot: 23 high
43
QUICKSORT - PARTITION
int partition( int *a, int low, int high ) {
int left, right;
int pivot_item;
pivot_item = a[low];
pivot = left = low;
right = high; Move the left pointer while
while ( left < right ) { it points to items <= pivot
/* Move left while item < pivot */
while( a[left] <= pivot_item ) left++;
/* Move right while item > pivot */
while( a[right] >= pivot_item ) right--;
if ( left < right ) SWAP(a,left,right);
} left right
Move right
/* right is final position for the pivot */ similarly
a[low] = a[right];
23 12 15
a[right] 38 42 18 36 29 27
= pivot_item;
return right;
}
low pivot: 23 high
44
QUICKSORT - PARTITION
int partition( int *a, int low, int high ) {
int left, right;
int pivot_item;
pivot_item = a[low];
pivot = left = low;
Swap the two items
right = high; on the wrong side of the pivot
while ( left < right ) {
/* Move left while item < pivot */
while( a[left] <= pivot_item ) left++;
/* Move right while item > pivot */
while( a[right] >= pivot_item ) right--;
if ( left < right ) SWAP(a,left,right);
}
left
/* right is final right for the pivot */
position
a[low] = a[right];
a[right]
23 12 15= pivot_item;
38 42 18 36 29 27
return right;
pivot: 23
}
low high
45
QUICKSORT - PARTITION
int partition( int *a, int low, int high ) {
int left, right;
int pivot_item; left and right
pivot_item = a[low]; have swapped over,
pivot = left = low;
right = high; so stop
while ( left < right ) {
/* Move left while item < pivot */
while( a[left] <= pivot_item ) left++;
/* Move right while item > pivot */
while( a[right] >= pivot_item ) right--;
if ( left < right ) SWAP(a,left,right);
}
/* right isright left
final position for the pivot */
a[low] = a[right];
a[right]
23 12 15= pivot_item;
18 42 38 36 29 27
return right;
}
low pivot: 23 high
46
QUICKSORT - PARTITION
int partition( int *a, int low, int high ) {
int left, right;
int pivot_item;
pivot_item = a[low];
pivot = left = low;
right = high;
right left
while ( left < right ) {
/* Move left while item < pivot */
23 12while(
15 a[left]
18 42 <=
38 pivot_item
36 29 ) 27left++;
/* Move right while item > pivot */
while( a[right] >= pivot_item ) right--;
low if ( left < right
pivot: 23 ) SWAP(a,left,right);
high
}
/* right is final position for the pivot */
a[low] = a[right];
Finally, swap the pivot
a[right] = pivot_item; and right
return right;
}
47
QUICKSORT - PARTITION
int partition( int *a, int low, int high ) {
int left, right;
int pivot_item;
pivot_item = a[low];
pivot = left = low;
right
right = high;
while ( left < right ) { pivot: 23
/* Move left while item < pivot */
18 12while(
15 a[left]
23 42<= pivot_item
38 36 29 27
) left++;
/* Move right while item > pivot */
while( a[right] >= pivot_item ) right--;
low high
if ( left < right ) SWAP(a,left,right);
}
/* right is final position for the pivot */
a[low] = a[right]; Return the position
a[right] = pivot_item; of the pivot
return right;
}
48
QUICKSORT - CONQUER
pivot: 23 Time Performance Worst Case
T (n) T (n 1) T (1) (n), T (1) 1
18 12 15 23 42 38 36 29 27 T ( n) ( n 2 )
n
T (n) (nlog (n))
51