Professional Documents
Culture Documents
Where,
T(n) is the time for DandC on any input of size n.
g(n) is the time to compute the answer directly for small inputs.
f(n) is time for dividing P & combining the solutions of subproblems.
The complexities of many divide and conquer algorithms is given by the recurrence of the
form:
T(1) n=1
T(n) =
aT(n/b)+f(n) n>1
Binary Search:-
Let ai (1≤i≤n) is a list of elements stored in non decreasing order. The searching
problem is to determine whether a given element is present in the list. If key ‘K’ is present
we have to determine the index value j such that a j=K. If K is not in the list j is set to be zero.
Let P= (n, al, . . . ah, K) denotes an instance of binary search problem. Divide &
Conquer can be used to solve this binary search problem. Let Small (P) be true if n=1. S(P)
will take the value i if K=ai , otherwise it will take 0.
If P has more than one element it can be divided into new sub-problems as follows:
Take an index q with in the range [l, h] & compare K with a q. There are three possibilities.
i. If K= aq the problem is immediately solved(Successful search)
ii. If K< aq , key x is to be searched only in sublist a l, al+1, . . ., aq-1.
iii. If K >aq , key x is to be searched only in sublist a q+1, aq+2, . . ., ah.
If q is chosen such that aq is the middle element i.e q=(n+1)/2, then the resulting
searching algorithm is known as Binary Search algorithm.
mid= ⌊(low+high)/2⌋;
if(K=a[mid]) then return mid;
else if (K<a[mid]) then
BinarySearch(a, low, mid-1, K);
else
BinarySearch(a,mid+1, high, K);
}
}
while(low≤high) do
{
mid=⌊(low+high)/2⌋;
if(x < a[mid]) then high=mid-1;
else if(x > a[mid]) then low=mid+1;
else return mid;
}
return 0;
}
Testing:-
To fully test binary search, we need not concern with the values of a[1:n]. By varying
x sufficiently, we can observe all possible computation sequences of BinarySearch without
taking different values for a.
Analysis:-
We do the analysis with frequency count(Key operation count) and space required
for the algorithm. In binary search the space is required to store n elements of the array
and to store the variables low, high, mid and x i.e. n+4 locations.
To find the time complexity of the algorithm, as the comparison count depends on
the specifics of the input, so we need to analyze best case, average case & worst case
efficiencies separately.
We assume only one comparison is needed to determine which of the three
possibilities of if condition in the algorithm holds. Let us take an array with 14 elements.
Index pos 1 2 3 4 5 6 7 8 9 10 11 12 13 14
Elements -10 -6 -3 -1 0 2 4 9 12 15 18 19 22 30
comparisons 3 4 2 4 3 4 1 4 3 4 2 4 3 4
From the above table we can conclude that, no element requires more the 4 comparisons.
The average number of comparisons required is (sum of count of comparisons/number of
elements) i.e 45/14=3.21 comparisons per successful search on average.
There are 15 possible ways that an unsuccessful search may terminate depending
on the value of x. if x < a[1], the algorithm requires three comparisons to determine x is not
present. For all the remaining possibilities the algorithm requires 4 element comparisons.
Thus the average number of comparisons for an unsuccessful search is
(3+14*4)/15=59/15=3.93.
To derive the generalized formula and for better understanding of algorithm is to
consider the sequence of values for mid that are produced by BinarySearch for all possible
values of x. these possible values can described using binary decision tree in which the
value in each node is the value of mid. The below figure is the decision tree for n=14.
11
3
5 9 13
1
6 8 10 12 14
4
2
In the above decision tree, each path through the tree represents a sequence of
comparisons in the binary search method. If x is present, then algorithm will end at one of
the circular node (internal nodes) that lists the index into the array where x was found. If x
is not present, the algorithm will terminate at one of the square nodes (external nodes).
Theorem:
If n is in the range [2k-1, 2k), then BinarySearch makes at most k element comparisons for
successful search and either k-1 or k comparisons for an unsuccessful search. (i.e. The time
for a successful search is O(logn) and for unsuccessful search is Θ(logn)).
Proof:
Let us consider a binary decision tree, which describes the function of Binary search
on n elements. Here all successful search end at a circular node, where as all unsuccessful
search will end at square node. If 2k-1≤n<2k, then all circular nodes are at levels 1,2,…,k,
where as all square nodes are at levels k & K+1(root node is at level 1). The number of
element comparisons needed to terminate at a circular node on level i is i, where as the
number of element comparisons needed to terminate at a square node at level i is only i-1,
hence the proof.
The above proof will tell the worst case time complexity is O(logn) for successful
search & Θ(logn) for unsuccessful search.
….
= T(2k-k)+k
=T(1)+k n=2k
C(n) =1+k=k logn=klog2
To determine the average case efficiency, we have to equate, the size of the decision
tree to the number of element comparisons in the algorithm.
The distance of a node from the root is one less than its level. Let the internal path
length I is the sum of the distances of all internal nodes from the root. Similarly, the
external path length E is the sum of the distances of all external nodes from the root.
For any binary tree with n internal nodes, E & I are related by the formula
E=I+2n
Let As(n) be the average number of comparisons for successful search, and A u(n) be
the average number of comparisons for unsuccessful search. The number of comparisons
needed to find an element represented by an internal node is one more than the distance of
this node from the root. Therefore
As(n)=1+I/n
The number of comparisons on any path from root to external node is distance
between the root and the external node. Since binary tree has n+1 external nodes
Au(n)=E/(n+1)
As(n)=(1+1/n) Au(n)-1
From the above formula we can conclude that, As(n) & Au(n) are directly related the
minimum value of As(n) (& Au(n)) is achieved by binary decision tree which has minimum
external & internal path length. This is possible when all external nodes are in on adjacent
Quick Sort
In quick sort, the division of array into two sub arrays is made such that sorted
subarrays are need not to be merged later. This can be done by rearranging the elements of
a[1:n] such that, a[i]≤a[j] for all i between 1 and m and for all j between m+1 to n for some
m, such that 1≤m≤n. Thus the elements in a[1:m] and a[m+1:n] can be independently
sorted, no merge is required. The rearrangement of the elements is accomplished by
picking some element of a[ ], say P=a[1] and reordering the other elements so that all
elements appearing before P in a[1:n] are less than or equal to P and all the element
appearing after P are greater than or equal to P. This rearranging is called Partitioning.
i j
P All are ≤ P ≥P …….. ≤P All are ≥ P
j i
P All are ≤ P ≤P ≥P All are ≥ P
ALGORITHM Partition(A[l..r])
//Partitions a subarray by using the first element as a pivot
//Input: Subarray of array A[0..n − 1], defined by its left and right indices l and r (l<r)
//Output: Partition of A[l..r], with the split position returned as this function’s value
p←A[l]
i ←l; j ←r + 1
repeat
repeat i ←i + 1 until A[i]≥ p
repeat j ←j − 1 until A[j ]≤ p
swap(A[i], A[j ])
until i ≥ j
swap(A[i], A[j ]) //undo last swap when i ≥ j
swap(A[l], A[j ])
return j
Analysis:-
Quick algorithm is a recursive algorithm.
The size of the input is specified by the number of elements we need to sort.
The key operation of the algorithm is comparison.
The count of the comparison is not just depends only on the size of the input, it also
depends on the type of the input i.e. sorted array, unsorted array, partially sorted
0 if n=1
T(n)=
2T(n/2)+ n otherwise
By applying the Master’s theorem,
T(n)=aT(n/b)+f(n)
Therefore a=2, b=2, f(n)=n=n1=nd so, d=1.
So, according to Master theorem T(n) is given by
Θ(nd) if a<bd
Θ(nlogba) if a>bd
For the quick sort algorithm, a=bd holds good,
T(n)∈Θ(nlogn)
Worst case Analysis:
The worst case of the quick sort occurs, when at each invocation of the quick
sort algorithm, the current array is partitioned into two sub arrays with one of them being
empty.
This situation occurs when the input list is arranged in either ascending or descending
order.
∴ T(n)= T(0)+T(n-1)+n
=T(n-1)+n //T(0)=0
By the method of backward substitution
T(n) = T(n-1)+n
= T(n-2)+(n-1)+n
=T(n-3)+(n-2)+(n-1)+n
=T(n-4)+(n-3)+(n-2)+(n-1)+n
…..
=T(n-i)+(n-i-1)+(n-i-2)+ . . . . +(n-3)+(n-2)+(n-1)+n
.
….
=T(n-n)+(n-(n-1))+(n-(n-2))+ . . . . +(n-3)+(n-2)+(n-1)+n
=1+2+3+4+. . . . +(n-3)+(n-2)+(n-1)+n
T(n)=n(n+1)/2 n2
T(n)∈Θ(n2)
The average case of the quick sort will appear for typical or random or real time
input. Where the given array may not be exactly portioned into two equal parts as in best
case or the sub-arrays are not skewed as in worst case.
T(n)=1/n [T (k 1) T (n k ) (n 1)]
k 1
Multiply by n
nT(n)= [T (k 1) T (n k ) (n 1)]
k 1
n n
nT(n)= [T (k 1) T (n k )] + (n 1)
k 1 k 1
Eqn 1
[T (k 1) T (n k )] =T(0)+T(n-1)+T(1)+T(n-2)+T(2)+T(n-3)+ . . . . +T(n-2)+
k 1
T(1)+T(n-1)+T(0)
[T (k 1) T (n k )] =2[T(0)+T(1)+T(2)+. . . .+T(n-2)+T(n-1)]
k 1
Eqn 2
(n 1) =(n+1)(n-1+1)= (n+1)n
k 1
Eqn 3
nT(n)-(n-1)T(n-1)= 2T(n-1)+n2+n-n2+n
nT(n)-(n-1)T(n-1)=2T(n-1)+2n
nT (n) (n 1)T (n 1) 2n
= +
n(n 1) n(n 1) n(n 1)
T (n) T ( n 1) 2
= +
(n 1) n n 1
T ( n 2) 2 2
= + + // Replace n by (n-1)
n 1 n n 1
T ( n 3) 2 2 2
= + + +
n2 n 1 n n 1
T ( n 4) 2 2 2 2
= + + + +
n3 n 2 n 1 n n 1
….
T ( 0) 2 2 2 2 2 2
= + + + +....+ + +
1 2 3 4 n 1 n n 1
2 2 2 2 2 2
= 0+ + + +....+ + + // T(0)=0
2 3 4 n 1 n n 1
T ( n) 1 1 1 1 1 1
= 2( + + + . . . . + + + )
(n 1) 2 3 4 n 1 n n 1
n 1
1
n 1
T ( n) 1
=2 = 2 di
(n 1) i2 i i 2
i
T ( n)
= 2 log i
n 1
(n 1) 2
T ( n)
= 2[log(n+1)-log2] 2 log( n 1)
(n 1)
T(n)=(n+1)2log(n+1) nlogn
T(n) (nlogn)