DAA Notes Module 2
DAA Notes Module 2
RV Educational Institutions®
RV Institute of Technology and Management
(Affiliated to VTU, Belagavi)
th
JP Nagar 8 Phase, Bengaluru - 560076
Department of Information Science and Engineering
Prepared By :
Dr. Shruthi P.
Module -2
Divide and Conquer
2.1 Divide And Conquer Algorithm
In this approach ,we solve a problem recursively by applying 3 steps as shown in Fig 2.1.
1. DIVIDE-break the problem into several sub problems of smaller size.
2. CONQUER-solve the problem recursively.
3. COMBINE-combine these solutions to create a solution to the original problem.
Given a two pan fair balance and N identically looking coins, out of which only one coin is lighter
(or heavier). To figure out the odd coin, how many minimum number of weighing are required in
the worst case?
Difficult: Given a two pan fair balance and N identically looking coins out of which only one
coin may be defective. How can we trace which coin, if any, is odd one and also determine
whether it is lighter or heavier in minimum number of trials in the worst case?
Approach 1: Linear method
In this method taking 2 and weighing repeatedly takes (n-1) comparisons.
Fig 2.2: Divide and conquer method for Counter fiet Coin problem
Max-Min Problem
Problem Statement: The Max-Min Problem in algorithm analysis is finding the maximum and
minimum value in an array.
Solution
• To find the maximum and minimum numbers in a given array numbers[] of size n, the
following algorithm can be used. First we are representing the naive method and then we will
present divide and conquer approach.
• Naïve Method
• Naïve method is a basic method to solve any problem. In this method, the maximum and
minimum number can be found separately. To find the maximum and minimum numbers, the
following straightforward algorithm can be used.
Analysis
• The number of comparison in Naive method is 2n - 2.
• The number of comparisons can be reduced using the divide and conquer approach.
Following is the technique: Divide and Conquer Approach
• In this approach, the array is divided into two halves. Then using recursive approach maximum
and minimum numbers in each halves are found. Later, return the maximum of two maxima of
each half and the minimum of two minima of each half.
• In this given problem, the number of elements in an array is y−x+1y−x+1, where y is greater than
or equal to x.
• Max−Min(x,y)Max−Min(x,y) will return the maximum and minimum values of an
array numbers[x...y]numbers[x...y].
Algorithm: Max - Min(i,j,max,min)
if (i==j) then max:=min:=a[i]; // small(P)
else if (i=j-1) then //small(P)
{ if(a[i]<a[j]) then
{
max:=a[j]; min:=a[i];
}
else
{
max:=a[i]; min:=a[j];
}
else
{
mid:= └(i+j)/2┘;
Max-Min(i,mid,max.min);
Max-Min(mid+1,j,max1,min1);
}
}
Example
a: [1] [2] [3] [4] [5] [6] [7] [8] [9]
22 13 -5 -8 15 60 17 31 47
A good way of keeping track of recursive calls is to build a tree by adding a node each time
a new call is made. On the array a[ ] above, the following tree is produced as shown in Fig 2.3.
• Let us assume that n is in the form of power of 2. Hence, n = 2k where k is height of the
recursion tree.
• Compared to Naïve method, in divide and conquer approach, the number of comparisons is
less. However, using the asymptotic notation both of the approaches are represented by O(n).
Features:
• Is a comparison based algorithm
• Is a stable algorithm
• Is a perfect example of divide & conquer algorithm design strategy
Example:
Apply merge sort for the following list of elements: 6, 3, 7, 8, 2, 4, 5, 1
Solution: Merge sort illustration is shown in Fig 2.4.
Now we add equations (3) through (8) : the sum of their left-hand sides
will be equal to the sum of their right-hand sides:
T(N) / N + T(N/2) / (N/2) + T(N/4) / (N/4) + … + T(2)/2 =
T(N/2) / (N/2) + T(N/4) / (N/4) + ….+ T(2) / 2 + T(1) / 1 + LogN
(LogN is the sum of 1s in the right-hand sides)
Advantages:
• Number of comparisons performed is nearly optimal.
• Mergesort will never degrade to O(n2)
• It can be applied to files of any size
Limitations:
• Uses O(n) additional memory.
Algorithm
Example: Sort by quick sort the following list: 5, 3, 1, 9, 8, 2, 4, 7, show recursion tree.
Illustration of quick sort is shown in Fig 2.5.
1. the for loop stops when the indexes cross, hence there are N iterations
2. swap is one operation – disregarded
3. Two recursive calls:
a. Best case: each call is on half the array, hence time is 2T(N/2)
b. Worst case: one array is empty, the other is N-1 elements, hence time is T(N-1)
o the time to sort the right partition with N-i-1 elements, plus
o the time to build the partitions
Best-case analysis:
The pivot is in the middle
T(N) = 2T(N/2) + cN
Divide by N:
T(N) / N = T(N/2) / (N/2) + c
Telescoping:
T(N/2) / (N/2) = T(N/4) / (N/4) + c
T(N/4) / (N/4) = T(N/8) / (N/8) + c
……
T(2) / 2 = T(1) / (1) + c
and subtract:
NT(N) - (N-1)T(N-1) = 2T(N-1) + 2cN -c
Divide by N(N+1):
T(N)/(N+1) = T(N-1)/N + 2c/(N+1)
Telescope:
T(N)/(N+1) = T(N-1)/N + 2c/(N+1)
T(N-1)/(N) = T(N-2)/(N-1)+ 2c/(N)
T(N-2)/(N-1) = T(N-3)/(N-2) + 2c/(N-1)
….
T(2)/3 = T(1)/2 + 2c /3
Solution
In this algorithm, we want to find whether element x belongs to a set of numbers stored in an
array numbers[]. Where l and r represent the left and right index of a sub-array in which searching
operation should be performed.
Algorithm: Binary-Search(numbers[], x, l, r)
if l = r then
return l
else
m := ⌊(l + r) / 2⌋
if x ≤ numbers[m] then
return Binary-Search(numbers[], x, l, m)
else
return Binary-Search(numbers[], x, m+1, r)
Analysis
Linear search runs in O(n) time. Whereas binary search produces the result in O(log n) time.
Let T(n) be the number of comparisons in worst-case in an array of n elements.
Hence,
The difference between O(log(N)) and O(N) is extremely significant when N is large: for any practical
problem it is crucial that we avoid O(N) searches. For example, suppose your array contains 2 billion (2
* 10**9) values. Linear search would involve about a billion comparisons; binary search would require
only 32 comparisons!
The space requirements for the recursive and iterative versions of binary search are different. Iterative
Binary Search requires only a constant amount of space, while Recursive Binary Search requires space
proportional to the number of comparisons to maintain the recursion stack.
Naïve Method
First, we will discuss naïve method and its complexity. Here, we are calculating Z = X × Y. Using
Naïve method, two matrices (X and Y) can be multiplied if the order of these matrices are p × q and q
× r. Following is the algorithm.
Where:
M1 = (A00 + A11) * (B00 + B11)
M2 = (A10 + A11) * B00
M3 = A00 * (B01 – B11)
M4 = A11 * (B10 – B00)
M5 = (A00 + A01) * B11
M6 = (A10 – A00) * (B00 + B01)
M7 = (A01 – A11) * (B10 + B11)
Analysis:
• Input size: n – order of square matrix.
• Basic operation:
o Multiplication (7)
o Addition (18)
o Subtraction (4)
• No best, worst, average case
• Let M(n) be the number of multiplication’s made by the algorithm, Therefore we have:
M (n) = 7 M(n/2) for n > 1
M (1) = 1
Assume n = 2k
M (2k) = 7 M(2k-1)
= 7 [7 M(2k-2)]
= 72 M(2k-2)
…
= 7i M(2k-i)
When i=k
= 7k M(2k-k)
= 7k
Following Fig 2.6 shows the major variations of decrease & conquer approach.
Decrease by a constant :(usually by 1):
Algorithm:
ALGORITHM DFS (G)
//implements DFS traversal of a given graph
//i/p: Graph G = { V, E}
//o/p: DFS tree
Mark each vertex in V with 0 as a mark of being “unvisited”
count <--0
for each vertex v in V do
if v is marked with 0
dfs(v)
dfs(v)
count <--count + 1
mark v with count
for each vertex w in V adjacent to v do
if w is marked with 0
dfs(w)
Algorithm:
ALGORITHM BFS (G)
//implements BFS traversal of a given graph
//i/p: Graph G = { V, E}
//o/p: BFS tree/forest
bfs(v)
count <-- count + 1
mark v with count and initialize a queue with v
while the queue is NOT empty do
for each vertex w in V adjacent to front’s vertex v do
if w is marked with 0
count<-- count + 1
mark w with count
add w to the queue
remove vertex v from the front of the queue
NOTE:
There is no solution for topological sorting if there is a cycle in the digraph .
[MUST be a DAG]
Topological sorting problem can be solved by using
1. DFS method
2. Source removal method
int topologicalOrderTraversal( ){
int numVisitedVertices = 0;
while(there are more vertices to be visited){
if(there is no vertex with in-degree 0)
break;
else{
select a vertex v that has in-degree 0;
visit v;
numVisitedVertices++;
delete v and all its emanating edges;
}
}
return numVisitedVertices;
}
*****