0% found this document useful (0 votes)
113 views

Devide and Conqure Rule

Divide and Conquer is an algorithm design paradigm that involves dividing a problem into smaller subproblems, conquering the subproblems by solving them recursively, and then combining the solutions to solve the original problem. Some common algorithms that use this approach include Merge Sort, Quick Sort, and Binary Search. Binary Search uses a divide and conquer approach to recursively search half of a sorted array for a target value in logarithmic time complexity of O(log n). Merge Sort uses divide and conquer to recursively split an unsorted array into single element subarrays which are then merged back together in sorted order, resulting in O(n log n) time complexity. Quicksort also uses divide and conquer, but picks a pivot element and partitions the array into sub

Uploaded by

Abhishek Nandy
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
113 views

Devide and Conqure Rule

Divide and Conquer is an algorithm design paradigm that involves dividing a problem into smaller subproblems, conquering the subproblems by solving them recursively, and then combining the solutions to solve the original problem. Some common algorithms that use this approach include Merge Sort, Quick Sort, and Binary Search. Binary Search uses a divide and conquer approach to recursively search half of a sorted array for a target value in logarithmic time complexity of O(log n). Merge Sort uses divide and conquer to recursively split an unsorted array into single element subarrays which are then merged back together in sorted order, resulting in O(n log n) time complexity. Quicksort also uses divide and conquer, but picks a pivot element and partitions the array into sub

Uploaded by

Abhishek Nandy
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 11

Divide and Conquer

Like dynamic and greedy methods, Divide and Conquer is an algorithmic paradigm. A
typical Divide and Conquer algorithm solves a problem using following three steps.

1. Divide problem into several smaller sub problems


o Normally, the sub problems are similar to the original
2. Conquer the sub problems by solving them recursively
o Base case: solve small enough problems by brute force
3. Combine the solutions to get a solution to the sub problems
o And finally a solution to the original problem
4. Divide and Conquer algorithms are normally recursive.

The following algorithms are based on divide-and-conquer algorithm design paradigm −

 Merge Sort

 Quick Sort

 Binary Search

Binary search

15 27 33 83 92 99

Search=99, low=0, high=5, mid= (low + high)/2=0+5=2

Pass 1

15 27 33 83 92 99
| Check for 99

Search=99, low=2+1=3, high=5, mid= (low + high)/2=3+5=4

Pass 2

15 27 33 83 92 99
| Check for 99

Search=99, low=5, high=5, mid= (low + high)/2=5+5=5

Pass 3
15 27 33 83 92 99
| finds 99

Pseudo code for binary search

Binary Search (arr[],l, r, x)


{
If (r >= l) {
mid = ( l + r ) / 2;

If (arr[mid] == x)
Return mid;

If (arr[mid] > x)
Return Binary Search (arr, l, mid - 1, x);

Return binarySearch(arr, mid + 1, r, x);


}

Return -1;
}

Complexity of binary search

The recurrence relation for Binary search can be given as

T (n) = 1 for n<=2

Or

= T (n/2) +c for n>2

Let say the iteration in Binary Search terminates after k iterations. In the above example,
it terminates after 3 iterations, so here k = 3
At each iteration, the array is divided by half. So let’s say the length of array at any
iteration is n.
At Iteration 1,
Length of array = n
At Iteration 2,
Length of array = n⁄2
At Iteration 3,
Length of array = (n⁄2)⁄2 = n⁄22
Therefore, after Iteration k,
Length of array = n⁄2k
Also, we know that after
After k divisions, the length of array becomes 1
Therefore
Length of array = n⁄2k = 1
=> n = 2k
Applying log function on both sides:
=> log2 (n) = log2 (2k)
=> log2 (n) = k log2 (2)
As (loga (a) = 1)
Therefore,
=> k = log2 (n)
Hence the time complexzity of Binary Search is
log2 (n)

Merge sort

Let's consider an array with values {14, 7, 3, 12, 9, 11, 6, and 12}

Below, we have a pictorial representation of how merge sort will sort the given array.
In merge sort we follow the following steps:

1. We take a variable p and store the starting index of our array in this. And we
take another variable r and store the last index of array in it.
2. Then we find the middle of the array using the formula (p + r)/2 and mark
the middle index as q, and break the array into two subarrays, from p to q and
from q + 1 to r index.
3. Then we divide these 2 subarrays again, just like we divided our main array
and this continues.
4. Once we have divided the main array into subarrays with single elements,
then we start merging the subarrays.

Pseudo code for merge sort

I/P: Unsorted array of size n


O/P: sorted array of size n
Mergesort (A, low, high)
{
If (low<high)
{
Mid= (low+high)/2
Mergesort (A, low, mid)
Mergesort (A, mid+1, high)
Merge (A, low, mid, high)
}
Merge (A, low, mid, high)
{
n1=mid-low+1
n2=high-mid
for (i=0; i<n1; i++)
L[i] =A[i]
for (j=0;j<n2;j++)
R[j]=A[j+mid+1]
L[i]=9999
R[j]=9999
i=0
j=0
For (k=low;k<=high;k++)
If (L[i] <=R[j])
A[k] =L[i]
I=i+1
Else
A[k] =R[j]
J=j+1
}

Complexity of merge sort

 1. First, we spend time O(1) for computing m.

 2. Then, we make two recursive calls to Merge Sort, with arrays of sizes ⌊(n − 1)/2⌋
and ⌈(n − 1)/2⌉.

3. Finally, we call Merge. Merge goes through the two subarrays with one loop, always
increasing one of i and j.

Time to merge two arrays each N/2 elements is linear, i.e. N

Thus we have:

(1) T(1) = 1

(2) T(N) = 2T(N/2) + N

Next we will solve this recurrence relation. First we divide (2) by N:

(3) T(N) / N = T(N/2) / (N/2) + 1

N is a power of two, so we can write

(4) T(N/2) / (N/2) = T(N/4) / (N/4) +1

(5) T(N/4) / (N/4) = T(N/8) / (N/8) +1

(6) T(N/8) / (N/8) = T(N/16) / (N/16) +1

(7) ……
(8) T(2) / 2 = T(1) / 1 + 1

After constituting equation (1) to (8) we get

T(N) = N + NlogN = O(NlogN)

Hence the complexity of the Merge Sort algorithm is O (NlogN).


Quik sort
Pseudo code
Complexity of quick sort:

The worst-case choice: the pivot happens to be the largest (or

smallest) item.

• Then one subarray is always empty.

• The second subarray contains n − 1 elements, i.e. all the

elements other than the pivot.

• Quicksort is recursively called only on this second group.

However, quicksort is fast on the “randomly scattered” pivots

• At each next step for n ≥ 1, the number of comparisons is

one less, so that T(n) = T(n − 1) + (n − 1); T(1) = 0.

• “Telescoping” T(n) − T(n − 1) = n − 1:

T(n)+T(n − 1)+T(n − 2)+. . .+T(3)+T(2)

−T(n − 1)−T(n − 2)−. . .−T(3)−T(2)− T(1)

= (n − 1) + (n − 2) +. . .+ 2 + 1 − 0

T(n)= (n − 1) + (n − 2) +. . .+ 2 + 1 =(n−1)n/2

This yields that T (n) ∈ Ω (n2).


For any pivot position i; i ∈ {0, . . . , n − 1}:

• Time for partitioning an array : cn

• The head and tail subarrays contain i and n − 1 − i items,

respectively: T(n) = cn + T(i) + T(n − 1 − i)

Best case
T(n) = partition(n) + 2*T(n/2) // partition(n) = n
= n + 2*T(n/2)
= 2*T(n/2) + n

T(1) = 1 // For the if-check operation


T(n) = 2*T(n/2) + n // T(n/2) = 2*T(n/4) + (n/2)

= 2*[ 2*T(n/4) + n/2 ] + n


= 22*T(n/4) + n + n
= 22*T(n/4) + 2n // T(n/4) = 2*T(n/8) + (n/4)

= 22*[ 2*T(n/8) + (n/4) ] + 2n


= 23*T(n/8) + 22*(n/4) + 2n
= 23*T(n/8) + n + 2n
= 23*T(n/8) + 3n

= 24*T(n/16) + 4n
and so on....

= 2k*T(n/(2k)) + k*n // Keep going until: n/(2k) = 1 <==> n =


k
2

= 2k*T(1) + k*n
= 2k*1 + k*n
= 2k + k*n // n = 2k
= n + k*n
= n + (lg(n))*n
= n*( lg(n) + 1 )
~= n*lg(n))

Average case:

If the split induced by RANDOMIZED_PARTITION puts constant fraction of


elements on one side of the partition, then the recurrence tree has depth
(lgn) and (n) work is performed at (lg n) of these level. This is an intuitive
argument why the average-case running time of RANDOMIZED_QUICKSORT
is (n lg n).

Let T(n) denotes the average time required to sort an array of n elements. A call
to RANDOMIZED_QUICKSORT with a 1 element array takes a constant time, so
we have T(1) = (1).
After the split RANDOMIZED_QUICKSORT calls itself to sort two subarrays.
The average time to sort an array A[1 . . q] is T[q] and the average time to sort
an array A[q+1 . . n] is T[n-q]. We have
T(n) = 1/n (T(1) + T(n-1) + n-1∑q=1 T(q) + T(n-q))) +
(n) ----- 1
We know from worst-case analysis

T(1) = (1) and T(n -1) = O(n2)


T(n) = 1/n ( (1) + O(n2)) + 1/n n-1∑q=1 (r(q) + T(n - q)) + (n)
= 1/n n-1∑q=1(T(q) + T(n - q)) + (n) ------
-2
= 1/n[2 n-1∑k=1(T(k)] + (n)
= 2/n n-1∑k=1(T(k) + (n) --------
-3
Solve the above recurrence using substitution method. Assume inductively
that T(n) ≤ anlgn + b for some constants a > 0 and b > 0.

If we can pick 'a' and 'b' large enough so that n lg n + b > T(1). Then for n >
1, we have
T(n) ≥ n-1∑k=1 2/n (aklgk + b) + (n)
= 2a/n n-1∑k=1 klgk - 1/8(n2) + 2b/n (n -1) + (n) -------
4
At this point we are claiming that
n-1
∑k=1 klgk ≤ 1/2 n2 lgn - 1/8(n2)
Stick this claim in the equation 4 above and we get

T(n) ≤ 2a/n [1/2 n2 lgn - 1/8(n2)] + 2/n b(n -1) + (n)


≤ anlgn - an/4 + 2b + (n) ---------
-5
In the above equation, we see that (n) + b and an/4 are polynomials and we
certainly can choose 'a' large enough so that an/4 dominates (n) +b.

We conclude that QUICKSORT's average running time is (n lg(n)).

You might also like