Divide and Conquer
Divide and Conquer
1
Chapter 1
Like Greedyand Dynamic Programming, Divide and Conquer is an algorithmic paradigm. A typical Divide
and Conquer algorithm solves a problem using following three steps.
1. Divide: Break the given problem into subproblems of same type.
2. Conquer: Recursively solve these subproblems
3. Combine: Appropriately combine the answers
Following are some standard algorithms that are Divide and Conquer algorithms.
1) Binary Search is a searching algorithm. In each step, the algorithm compares the input element x with
the value of the middle element in array. If the values match, return the index of middle. Otherwise, if x is
less than the middle element, then the algorithm recurs for left side of middle element, else recurs for right
side of middle element.
2) Quicksort is a sorting algorithm. The algorithm picks a pivot element, rearranges the array elements in
such a way that all elements smaller than the picked pivot element move to left side of pivot, and all greater
elements move to right side. Finally, the algorithm recursively sorts the subarrays on left and right of pivot
element.
3) Merge Sort is also a sorting algorithm. The algorithm divides the array in two halves, recursively sorts
them and finally merges the two sorted halves.
4) Closest Pair of Points The problem is to find the closest pair of points in a set of points in x-y plane.
The problem can be solved in O(nˆ2) time by calculating distances of every pair of points and comparing the
distances to find the minimum. The Divide and Conquer algorithm solves the problem in O(nLogn) time.
5) Strassen’s Algorithm is an efficient algorithm to multiply two matrices. A simple method to multiply
two matrices need 3 nested loops and is O(nˆ3). Strassen’s algorithm multiplies two matrices in O(nˆ2.8974)
time.
6) Cooley–Tukey Fast Fourier Transform (FFT) algorithm is the most common algorithm for FFT.
It is a divide and conquer algorithm which works in O(nlogn) time.
7) Karatsuba algorithm for fast multiplication it does multiplication of two n-digit numbers in at
2
Divide and Conquer (D & C) vs Dynamic Programming (DP)
Both paradigms (D & C and DP) divide the given problem into subproblems and solve subproblems. How
to choose one of them for a given problem? Divide and Conquer should be used when same subproblems are
not evaluated many times. Otherwise Dynamic Programming or Memoization should be used. For example,
Binary Search is a Divide and Conquer algorithm, we never evaluate the same subproblems again. On the
other hand, for calculating nth Fibonacci number, Dynamic Programming should be preferred (See thisfor
details).
References
Source
http://www.geeksforgeeks.org/divide-and-conquer-set-1-find-closest-pair-of-points/
3
Chapter 2
Below solution divides the problem into subproblems of size y/2 and call the subproblems
recursively.
#include<stdio.h>
4
/* Function to calculate x raised to the power y in O(logn)*/
int power(int x, unsigned int y)
{
int temp;
if( y == 0)
return 1;
temp = power(x, y/2);
if (y%2 == 0)
return temp*temp;
else
return x*temp*temp;
}
Source
http://www.geeksforgeeks.org/write-a-c-program-to-calculate-powxn/
5
Category: C/C++ Puzzles Tags: Divide and Conquer
6
Chapter 3
Question: There are 2 sorted arrays A and B of size n each. Write an algorithm to find the median of the
array obtained after merging the above 2 arrays(i.e. array of length 2n). The complexity should be O(log(n))
Median: In probability theory and statistics, a median is described as the number separating the higher half
of a sample, a population, or a probability distribution, from the lower half.
The median of a finite list of numbers can be found by arranging all the numbers from lowest value to highest
value and picking the middle one.
For getting the median of input array { 12, 11, 15, 10, 20 }, first sort the array. We get { 10, 11, 12, 15, 20
} after sorting. Median is the middle element of the sorted array which is 12.
There are different conventions to take median of an array with even number of elements, one can take the
mean of the two middle values, or first middle value, or second middle value.
Let us see different methods to get the median of two sorted arrays of size n each. Since size of the set for
which we are looking for median is even (2n), we are taking average of middle two numbers in all below
solutions.
Method 1 (Simply count while Merging)
Use merge procedure of merge sort. Keep track of count while comparing elements of two arrays. If count
becomes n(For 2n elements), we have reached the median. Take the average of the elements at indexes n-1
and n in the merged array. See the below implementation.
Implementation:
#include <stdio.h>
7
of elements at index n-1 and n in the array obtained after
merging ar1 and ar2 */
for (count = 0; count <= n; count++)
{
/*Below is to handle case where all elements of ar1[] are
smaller than smallest(or first) element of ar2[]*/
if (i == n)
{
m1 = m2;
m2 = ar2[0];
break;
}
int n1 = sizeof(ar1)/sizeof(ar1[0]);
int n2 = sizeof(ar2)/sizeof(ar2[0]);
if (n1 == n2)
printf("Median is %d", getMedian(ar1, ar2, n1));
else
printf("Doesn't work for arrays of unequal size");
getchar();
return 0;
}
8
Time Complexity: O(n)
Example:
m1 = 26 m2 = 13.
9
m1 is greater than m2. So the subarrays become
Implementation:
#include<stdio.h>
if (n == 1)
return (ar1[0] + ar2[0])/2;
if (n == 2)
return (max(ar1[0], ar2[0]) + min(ar1[1], ar2[1])) / 2;
10
/* if m1 > m2 then median must exist in ar1[....m1] and ar2[m2...] */
else
{
if (n % 2 == 0)
return getMedian(ar2 + n/2 - 1, ar1, n - n/2 + 1);
else
return getMedian(ar2 + n/2, ar1, n - n/2);
}
}
getchar();
return 0;
}
/* Utility functions */
int max(int x, int y)
{
return x > y? x : y;
}
11
The basic idea is that if you are given two arrays ar1[] and ar2[] and know the length of each, you can check
whether an element ar1[i] is the median in constant time. Suppose that the median is ar1[i]. Since the array
is sorted, it is greater than exactly i values in array ar1[]. Then if it is the median, it is also greater than
exactly j = n – i – 1 elements in ar2[].
It requires constant time to check if ar2[j] 1) Get the middle element of ar1[] using array indexes left and
right. Let index of the middle element be i. 2) Calculate the corresponding index j of ar2[] j = n – i – 1 3)
If ar1[i] >= ar2[j] and ar1[i]
Example:
Middle element of ar1[] is 7. Let us compare 7 with 23 and 30, since 7 smaller than both 23 and 30, move to
right in ar1[]. Do binary search in {10, 13}, this step will pick 10. Now compare 10 with 15 and 23. Since 10
is smaller than both 15 and 23, again move to right. Only 13 is there in right side now. Since 13 is greater
than 11 and smaller than 15, terminate here. We have got the median as 12 (average of 11 and 13)
Implementation:
#include<stdio.h>
int getMedianRec(int ar1[], int ar2[], int left, int right, int n);
i = (left + right)/2;
j = n - i - 1; /* Index of ar2[] */
12
if (i == 0 || ar2[j] > ar1[i-1])
return (ar1[i] + ar2[j])/2;
else
return (ar1[i] + ar1[i-1])/2;
}
getchar();
return 0;
}
13
// last element of ar2
if (ar2[n-1] < ar1[0])
return (ar2[n-1]+ar1[0])/2;
References:
http://en.wikipedia.org/wiki/Median
http://ocw.alfaisal.edu/NR/rdonlyres/Electrical-Engineering-and-Computer-Science/6-046JFall-2005/30C68118-
E436-4FE3-8C79-6BAFBB07D935/0/ps9sol.pdf ds3etph5wn
Asked by Snehal
Please write comments if you find the above codes/algorithms incorrect, or find other ways to solve the same
problem.
Source
http://www.geeksforgeeks.org/median-of-two-sorted-arrays/
Category: Arrays Tags: Divide and Conquer
Post navigation
← Database Management Systems | Set 1 C Language | Set 1 →
Writing code in comment? Please use code.geeksforgeeks.org, generate link and share the link here.
14
Chapter 4
Inversion Count for an array indicates – how far (or close) the array is from being sorted. If array is already
sorted then inversion count is 0. If array is sorted in reverse order that inversion count is the maximum.
Formally speaking, two elements a[i] and a[j] form an inversion if a[i] > a[j] and i Example:
The sequence 2, 4, 1, 3, 5 has three inversions (2, 1), (4, 1), (4, 3).
METHOD 1 (Simple)
For each element, count number of elements which are on right side of it and are smaller than it.
return inv_count;
}
15
How to get number of inversions in merge()?
In merge process, let i is used for indexing left sub-array and j for right sub-array. At any step in merge(),
if a[i] is greater than a[j], then there are (mid – i) inversions. because left and right subarrays are sorted, so
all the remaining elements in left-subarray (a[i+1], a[i+2] … a[mid]) will be greater than a[j]
16
Implementation:
#include <stdio.h>
#include <stdlib.h>
17
if (right > left)
{
/* Divide the array into two parts and call _mergeSortAndCountInv()
for each of the parts */
mid = (right + left)/2;
/* This funt merges two sorted arrays and returns inversion count in
the arrays.*/
int merge(int arr[], int temp[], int left, int mid, int right)
{
int i, j, k;
int inv_count = 0;
18
arr[i] = temp[i];
return inv_count;
}
Note that above code modifies (or sorts) the input array. If we want to count only inversions then we need
to create a copy of original array and call mergeSort() on copy.
References:
http://www.cs.umd.edu/class/fall2009/cmsc451/lectures/Lec08-inversions.pdf
http://www.cp.eng.chula.ac.th/~piak/teaching/algo/algo2008/count-inv.htm
Please write comments if you find any bug in the above program/algorithm or other ways to solve the same
problem.
Source
http://www.geeksforgeeks.org/counting-inversions/
Category: Arrays Tags: Divide and Conquer
Post navigation
← Sort elements by frequency | Set 1 Operating Systems | Set 4 →
Writing code in comment? Please use code.geeksforgeeks.org, generate link and share the link here.
19
Chapter 5
We are given an array of n points in the plane, and the problem is to find out the closest pair of points in
the array. This problem arises in a number of applications. For example, in air-traffic control, you may
want to monitor planes that come too close together, since this may indicate a possible collision. Recall the
following formula for distance between two points p and q.
The Brute force solution is O(nˆ2), compute the distance between each pair and return the smallest. We can
calculate the smallest distance in O(nLogn) time using Divide and Conquer strategy. In this post, a O(n x
(Logn)ˆ2) approach is discussed. We will be discussing a O(nLogn) approach in a separate post.
Algorithm
Following are the detailed steps of a O(n (Logn)ˆ2) algortihm.
Input: An array of n points P[]
Output: The smallest distance between two points in the given array.
As a pre-processing step, input array is sorted according to x coordinates.
1) Find the middle point in the sorted array, we can take P[n/2] as middle point.
2) Divide the given array in two halves. The first subarray contains points from P[0] to P[n/2]. The second
subarray contains points from P[n/2+1] to P[n-1].
3) Recursively find the smallest distances in both subarrays. Let the distances be dl and dr. Find the
minimum of dl and dr. Let the minimum be d.
20
4) From above 3 steps, we have an upper bound d of minimum distance. Now we need to consider the pairs
such that one point in pair is from left half and other is from right half. Consider the vertical line passing
through passing through P[n/2] and find all points whose x coordinate is closer than d to the middle vertical
line. Build an array strip[] of all such points.
5) Sort the array strip[] according to y coordinates. This step is O(nLogn). It can be optimized to O(n) by
recursively sorting and merging.
6) Find the smallest distance in strip[]. This is tricky. From first look, it seems to be a O(nˆ2) step, but it
is actually O(n). It can be proved geometrically that for every point in strip, we only need to check at most
21
7 points after it (note that strip is sorted according to Y coordinate). See thisfor more analysis.
7) Finally return the minimum of d and distance calculated in above step (step 6)
Implementation
Following is C/C++ implementation of the above algorithm.
// A divide and conquer program in C/C++ to find the smallest distance from a
// given set of points.
#include <stdio.h>
#include <float.h>
#include <stdlib.h>
#include <math.h>
// A Brute Force method to return the smallest distance between two points
// in P[] of size n
float bruteForce(Point P[], int n)
{
float min = FLT_MAX;
for (int i = 0; i < n; ++i)
for (int j = i+1; j < n; ++j)
if (dist(P[i], P[j]) < min)
min = dist(P[i], P[j]);
22
return min;
}
// Pick all points one by one and try the next points till the difference
// between y coordinates is smaller than d.
// This is a proven fact that this loop runs at most 6 times
for (int i = 0; i < size; ++i)
for (int j = i+1; j < size && (strip[j].y - strip[i].y) < min; ++j)
if (dist(strip[i],strip[j]) < min)
min = dist(strip[i], strip[j]);
return min;
}
23
// to the line passing through the middle point
Point strip[n];
int j = 0;
for (int i = 0; i < n; i++)
if (abs(P[i].x - midPoint.x) < d)
strip[j] = P[i], j++;
// Find the closest points in strip. Return the minimum of d and closest
// distance is strip[]
return min(d, stripClosest(strip, j, d) );
}
Output:
Time Complexity Let Time complexity of above algorithm be T(n). Let us assume that we use a O(nLogn)
sorting algorithm. The above algorithm divides all points in two sets and recursively calls for two sets. After
dividing, it finds the strip in O(n) time, sorts the strip in O(nLogn) time and finally finds the closest points
in strip in O(n) time. So T(n) can expressed as follows
T(n) = 2T(n/2) + O(n) + O(nLogn) + O(n)
T(n) = 2T(n/2) + O(nLogn)
T(n) = T(n x Logn x Logn)
Notes
1) Time complexity can be improved to O(nLogn) by optimizing step 5 of the above algorithm. We will
soon be discussing the optimized solution in a separate post.
2) The code finds smallest distance. It can be easily modified to find the points with smallest distance.
3) The code uses quick sort which can be O(nˆ2) in worst case. To have the upper bound as O(n (Logn)ˆ2),
a O(nLogn) sorting algorithm like merge sort or heap sort can be used
References:
http://www.cs.umd.edu/class/fall2013/cmsc451/Lects/lect10.pdf
http://www.youtube.com/watch?v=vS4Zn1a9KUc
http://www.youtube.com/watch?v=T3T7T8Ym20M
http://en.wikipedia.org/wiki/Closest_pair_of_points_problem
24
Source
http://www.geeksforgeeks.org/closest-pair-of-points/
Category: Misc Tags: Closest Pair of Points, Divide and Conquer
Post navigation
← Greedy Algorithms | Set 8 (Dijkstra’s Algorithm for Adjacency List Representation) Comparison of static
keyword in C++ and Java →
Writing code in comment? Please use code.geeksforgeeks.org, generate link and share the link here.
25
Chapter 6
Given two square matrices A and B of size n x n each, find their multiplication matrix.
Naive Method
Following is a simple way to multiply two matrices.
26
In the above method, we do 8 multiplications for matrices of size N/2 x N/2 and 4 additions. Addition of
two matrices takes O(N2 ) time. So the time complexity can be written as
Simple Divide and Conquer also leads to O(N3 ), can there be a better way?
In the above divide and conquer method, the main component for high time complexity is 8 recursive calls.
The idea of Strassen’s method is to reduce the number of recursive calls to 7. Strassen’s method is similar
to above simple divide and conquer method in the sense that this method also divide matrices to sub-matrices
of size N/2 x N/2 as shown in the above diagram, but in Strassen’s method, the four sub-matrices of result
are calculated using following formulae.
27
Time Complexity of Strassen’s Method
Addition and Subtraction of two matrices takes O(N2 ) time. So time complexity can be written as
Generally Strassen’s Method is not preferred for practical applications for following reasons.
1) The constants used in Strassen’s method are high and for a typical application Naive method works better.
2) For Sparse matrices, there are better methods especially designed for them.
3) The submatrices in recursion take extra space.
4) Because of the limited precision of computer arithmetic on noninteger values, larger errors accumulate in
Strassen’s algorithm than in Naive Method (Source: CLRS Book)
References:
Introduction to Algorithms 3rd Edition by Clifford Stein, Thomas H. Cormen, Charles E. Leiserson, Ronald
L. Rivest
https://www.youtube.com/watch?v=LOLebQ8nKHA
https://www.youtube.com/watch?v=QXY4RskLQcI
Please write comments if you find anything incorrect, or you want to share more information about the topic
discussed above
Source
http://www.geeksforgeeks.org/strassens-matrix-multiplication/
28