DAA-22-23
DAA-22-23
DAA-22-23
B.TECH.
(SEM V) THEORY EXAMINATION
2022-23 DESIGN & ANALYSIS OF
ALGORITHM
Time: 3 Hours Total Marks: 100
Note: Attempt all Sections. If you require any missing data, then choose suitably.
SECTION A
(b) Explain and compare best and worst time complexity of Quick Sort.
Quick sort algorithm is one of the most widely used sorting algorithms. It follows a divide and
conquer paradigm. We usually use Recursion in quicksort implementation. In each recursive call, a
pivot is chosen, then the array is partitioned in such a way that all the elements less than pivot lie to
the left and all the elements greater than pivot lie to the right. After every call, the chosen pivot
occupies its correct position in the array which it is supposed to as in a sorted array. So with each step,
our problem gets reduced by 2 which leads to quick sorting.
Time Complexity
A skip list is a probabilistic data structure. The skip list is used to store a sorted list of
elements or data with a linked list. It allows the process of the elements or data to view
efficiently. In one single step, it skips several elements of the entire list, which is why it is
known as a skip list.The skip list is an extended version of the linked list. It allows the user
to search, remove, and insert the element very quickly. It consists of a base list that includes
a set of elements which maintains the link hierarchy of the subsequent elements.
A problem is said to satisfy the Principle of Optimality if the subsolutions of an optimal solution of
the problem are themesleves optimal solutions for their subproblems.
Examples:
NP-HardProblem:
A Problem X is NP-Hard if there is an NP-Complete problem Y, such that Y is reducible to X in
polynomial time. NP-Hard problems are as hard as NP-Complete problems. NP-Hard Problem
need not be in NP class.
example:
1. Hamiltonian cycle.
2. optimization problem.
3. Shortest path
NP-Complete Problem:
A problem X is NP-Complete if there is an NP problem Y, such that Y is reducible to X in
polynomial time. NP-Complete problems are as hard as NP problems. A problem is NP-Complete
if it is a part of both NP and NP-Hard Problem. A non-deterministic Turing machine can solve NP-
Complete problem in polynomial time.
Example:
1. Decision problems.
2. Regular graphs
SECTION B
Merge sort is similar to the quick sort algorithm as it uses the divide and conquer approach to sort
the elements. It is one of the most popular and efficient sorting algorithm. It divides the given list
into two equal halves, calls itself for the two halves and then merges the two sorted halves. We have
to define the merge() function to perform the merging.The sub-lists are divided again and again
into halves until the list cannot be divided further. Then we combine the pair of one element lists
into two-element lists, sorting them in the process. The sorted two-element pairs is merged into the
four-element lists, and so on until we get the sorted list.
Algorithm
In the following algorithm, arr is the given array, beg is the starting element, and end is the
last element of the array.
END MERGE_SORT
while (j<n2)
QP23DP1_032 | 10-01-2023 15:13:03 | 117.55.241.162
{
a[k] = RightArray[j];
j++;
k++;
}
}
– Decrease-
O(log n) O(1) amortized
key
4.
5.
6. Add edge 7-6 in the MST
Step 2: Pick edge 8-2. No cycle is formed, include it.
7.
8. Add edge 8-2 in the MST
Step 3: Pick edge 6-5. No cycle is formed, include it.
Step 7: Pick edge 7-8. Since including this edge results in the cycle, discard it. Pick edge 0-
7. No cycle is formed, include it.
Step 8: Pick edge 1-2. Since including this edge results in the cycle, discard it. Pick edge 3-
4. No cycle is formed, include it.
Discuss LCS algorithm to compute Longest Common Subsequence of two given strings and
time complexity analysis.
QP23DP1_032 | 10-01-2023 15:13:03 | 117.55.241.162
Given two strings, S1 and S2, the task is to find the length of the Longest Common Subsequence,
i.e. longest subsequence present in both of the strings.
A longest common subsequence (LCS) is defined as the longest subsequence which is common in
all given input sequences.
Examples:
Input: S1 = “AGGTAB”, S2 = “GXTXAYB”
Output: 4
Explanation: The longest subsequence which is present in both strings is “GTAB”.
Input: S1 = “BD”, S2 = “ABCD”
Output: 2
Explanation: The longest subsequence which is present in both strings is “BD”.
Generate all the possible subsequences and find the longest among them that is present in both
strings using recursion.
Follow the below steps to implement the idea:
Create a recursive function [say lcs()].
Check the relation between the First characters of the strings that are not yet processed.
Depending on the relation call the next recursive function as mentioned
above.
Return the length of the LCS received as the answer.
int lcs(string X, string Y, int m, int n)
{
if (m == 0 || n == 0)
return 0;
if (X[m - 1] == Y[n - 1])
return 1 + lcs(X, Y, m - 1, n - 1);
else
return max(lcs(X, Y, m, n - 1),
lcs(X, Y, m - 1, n));
}
TimeComplexity: O(2m*n)
Auxiliary Space: O(1)
Explain and Write the Naïve-String string matching algorithm: Suppose the given pattern
p= aa b and given text T = a c a a b c.
Apply Naïve-String Matching algorithm on above Pattern (P) and Text
(T) to find the number of occurrences of P in T.
The naïve approach tests all the possible placement of Pattern P [1.......m] relative to text T [1......n].
We try shift s = 0, 1.......n-m, successively and for each shift s. Compare T [s+1.......s+m] to P
[1......m].
The naïve algorithm finds all valid shifts using a loop that checks the condition P [1.......m] = T
[s+1.......s+m] for each of the n - m +1 possible value of s.
NAIVE-STRING-MATCHER (T, P)
1. n ← length [T]
QP23DP1_032 | 10-01-2023 15:13:03 | 117.55.241.162
2. m ← length [P]
3. for s ← 0 to n -m
4. do if P [1.....m] = T [s + 1....s + m]
5. then print "Pattern occurs with shift" s
Analysis: This for loop from 3 to 5 executes for n-m + 1(we need at least m characters at the end)
times and in iteration we are doing m comparisons. So the total complexity is O (n-m+1).
SECTION C
2. Attempt any one part of the following: 10x1 = 10
(a) Examine the following recurrence
relation: (i) T (n) = T (n-1) + n 4
This sorting technique doesn't perform sorting by comparing elements. It performs sorting by
counting objects having distinct key values like hashing. After that, it performs some
arithmetic operations to calculate each object's index position in the output sequence.
Counting sort is not used as a general-purpose sorting algorithm.
Counting sort is effective when range is not greater than number of objects to be sorted. It
can be used to sort the negative input values.
1. Insert the new node the way it is done in Binary Search Trees.
2. Color the node red
3. If an inconsistency arises for the red-black tree, fix the tree according to the type of
discrepancy.
4. In Red black tree if imbalancing occurs then for removing it two methods are used that are:
a) Recoloring
b) Rotation
It is the most important operation performed on the binomial heap. Merging in a heap can be done by
comparing the keys at the roots of two trees, and the root node with the larger key will become the
child of the root with a smaller key than the other. The time complexity for finding a union is O(logn).
The function to merge the two trees is given as follows -
1. function merge(a,b)
2. if a.root.key ? b.root.key
3. return a.add(b)
4. else
5. return b.add(a)
To perform the union of two binomial heaps, we have to consider the below cases:
Case 1: If degree[x] is not equal to degree[next x], then move pointer ahead.
Case 3: If degree[x] = degree[next x] but not equal to degree[sibling[next x]] and key[x] < key[next
x] then remove [next x] from root and attached to x.
Case 4: If degree[x] = degree[next x] but not equal to degree[sibling[next x]] and key[x] > key[next
x] then remove x from root and attached to [next
In the above heap first, the pointer x points to the node 12 with degree B0, and the pointer next[x]
points the node 18 with degree B0. Node 7 with degree B1 is the sibling of 18, therefore, it is
represented as sibling[next[x]].
Now, first apply Case1 that says 'if degree[x] ≠ degree[next x] then move pointer ahead' but in the
above example, the degree[x] = degree[next[x]], so this case is not valid.
Now, apply Case2 that says 'if degree[x] = degree[next x] = degree[sibling(next x)] then Move
pointer ahead'. So, this case is also not applied in the above heap.
Now, apply Case3 that says ' If degree[x] = degree[next x] ≠ degree[sibling[next x]] and key[x] <
key[next x] then remove [next x] from root and attached to x'. We will apply this case because
the above heap follows the conditions of case 3 -
Now we will reapply the cases in the above binomial heap. First, we will apply case 1. Since x is
pointing to node 12 and next[x] is pointing to node 7, the degree of x is equal to the degree of next x;
therefore, case 1 is not valid.
Here, case 2 is valid as the degree of x, next[x], and sibling[next[x]] is equal. So, according to the
case, we have to move the pointer ahead.
Now, let's try to apply case 3, here, first condition of case3 is satisfied as degree[x] = degree[next[x]]
≠ degree[sibling[next[x]]], but second condition (key[x] < key[next x]) of case 3 is not satisfied.
Now, let's try to apply case 4. So, first condition of case4 is satisfied and second condition (key[x] >
key[next x]) is also satisfied. Therefore, remove x from the root and attach it to [next[x]].
Now, the pointer x points to node 3, next[x] points to node 15, and sibling[next[x]] points to the node
6. Since, the degree of x is equal to the degree of next[x] but not equal to the degree[sibling[next[x]]],
and the key value of x is less than the key value of next[x], so we have to remove next[x] and attach
it to x as shown below -
QP23DP1_032 | 10-01-2023 15:13:03 | 117.55.241.162
Now, x represents to the node 3, and next[x] points to node 6. Since, the degree of x and next[x] is
not equal, so case1 is valid. Therefore, move the pointer ahead. Now, the pointer x points the node 6.
The B4 is the last binomial tree in a heap, so it leads to the termination of the loop. The above tree is
the final tree after the union of two binomial heaps.
Time Complexity:
binomial heap is the collection of binomial trees, and every binomial tree satisfies the min-heap
property. It means that the root node contains a minimum value. Therefore, we only have to compare
the root node of all the binomial trees to find the minimum key. The time complexity of finding the
minimum key in binomial heap is O(logn).
(b) What are single source shortest paths? Write down Dijkstra’s algorithm for it.
The Single-Source Shortest Path (SSSP) problem consists of finding the shortest paths between a
given vertex v and all other vertices in the graph. Algorithms such as Breadth-First-Search (BFS) for
unweighted graphs or Dijkstra [1] solve this problem.
Dijkstra's Algorithm is a Graph algorithm that finds the shortest path from a source vertex to all
other vertices in the Graph (single source shortest path). It is a type of Greedy Algorithm that only
works on Weighted Graphs having positive weights. The time complexity of Dijkstra's Algorithm
is O(V2) with the help of the adjacency matrix representation of the graph. This time complexity can
be reduced to O((V + E) log V) with the help of an adjacency list representation of the graph,
where V is the number of vertices and E is the number of edges in the graph.
Dijkstra's Algorithm with an Example
The following is the step that we will follow to implement Dijkstra's Algorithm:
Step 1: First, we will mark the source node with a current distance of 0 and set the rest of the nodes
to INFINITY.
Step 3: For each neighbor N of the current node X: We will then add the current distance of X with
the weight of the edge joining X-N. If it is smaller than the current distance of N, set it as the new
current distance of N.
Step 5: We will repeat the process from 'Step 2' if there is any node unvisited left in the graph.
Let us now understand the implementation of the algorithm with the help of an example:
1. We will use the above graph as the input, with node A as the source.
2. First, we will mark all the nodes as unvisited.
3. We will set the path to 0 at node A and INFINITY for all the other nodes.
4. We will now mark source node A as visited and access its neighboring nodes.
Note: We have only accessed the neighboring nodes, not visited them.
5. We will now update the path to node B by 4 with the help of relaxation because the path to
node A is 0 and the path from node A to B is 4, and the minimum((0 + 4), INFINITY) is 4.
6. We will also update the path to node C by 5 with the help of relaxation because the path to
node A is 0 and the path from node A to C is 5, and the minimum((0 + 5), INFINITY) is 5.
Both the neighbors of node A are now relaxed; therefore, we can move ahead.
7. We will now select the next unvisited node with the least path and visit it. Hence, we will
visit node B and perform relaxation on its unvisited neighbors. After performing relaxation,
QP23DP1_032 | 10-01-2023 15:13:03 | 117.55.241.162
the path to node C will remain 5, whereas the path to node E will become 11, and the path to
node D will become 13.
8. We will now visit node E and perform relaxation on its neighboring nodes B, D, and F. Since
only node F is unvisited, it will be relaxed. Thus, the path to node B will remain as it is, i.e., 4,
the path to node D will also remain 13, and the path to node F will become 14 (8 + 6).
9. Now we will visit node D, and only node F will be relaxed. However, the path to node F will
remain unchanged, i.e., 14.
10. Since only node F is remaining, we will visit it but not perform any relaxation as all its
neighboring nodes are already visited.
11. Once all the nodes of the graphs are visited, the program will end.
1. A=0
2. B = 4 (A -> B)
3. C = 5 (A -> C)
4. D = 4 + 9 = 13 (A -> B -> D)
5. E = 5 + 3 = 8 (A -> C -> E)
6. F = 5 + 3 + 6 = 14 (A -> C -> E -> F)
Pseudocode:
Example:
It can be seen that for n =1, the problem has a trivial solution, and no solution exists for n =2 and n
=3. So first we will consider the 4 queens problem and then generate it to n - queens problem.
Given a 4 x 4 chessboard and number the rows and column of the chessboard 1 through 4.
Since, we have to place 4 queens such as q1 q2 q3 and q4 on the chessboard, such that no two queens
attack each other. In such a conditional each queen must be placed on a different row, i.e., we put
queen "i" on row "i."
Now, we place queen q1 in the very first acceptable position (1, 1). Next, we put queen q2 so that both
these queens do not attack each other. We find that if we place q2 in column 1 and 2, then the dead
end is encountered. Thus the first acceptable position for q2 in column 3, i.e. (2, 3) but then no
position is left for placing queen 'q3' safely. So we backtrack one step and place the queen 'q2' in (2, 4),
the next best possible solution. Then we obtain the position for placing 'q3' which is (3, 2). But later
this position also leads to a dead end, and no place is found where 'q4' can be placed safely. Then we
have to backtrack till 'q1' and place it to (1, 2) and then all other queens are placed safely by moving
q2 to (2, 4), q3 to (3, 1) and q4 to (4, 3). That is, we get the solution (2, 4, 1, 3). This is one possible
solution for the 4-queens problem. For another possible solution, the whole method is repeated for all
partial solutions. The other solutions for 4 - queens problems is (3, 1, 4, 2) i.e.
String Matching Algorithm is also called "String Searching Algorithm." This is a vital class
of string algorithm is declared as "this is the method to find a place where one is several
strings are found within the larger string."
Given a text array, T [1.....n], of n character and a pattern array, P [1......m], of m characters.
The problems are to find an integer s, called valid shift where 0 ≤ s < n-m and T
[s+1......s+m] = P [1......m]. In other words, to find even if P in T, i.e., where P is a substring
of T. The item of P and T are character drawn from some finite alphabet such as {0, 1} or {A,
B .....Z, a, b..... z}.
The Rabin-Karp-Algorithm
The Rabin-Karp string matching algorithm calculates a hash value for the pattern, as well as for each
M-character subsequences of text to be compared. If the hash values are unequal, the algorithm will
determine the hash value for next M-character sequence. If the hash values are equal, the algorithm
will analyze the pattern and the M-character sequence. In this way, there is only one comparison per
text subsequence, and character matching is only required when the hash values match.
RABIN-KARP-MATCHER (T, P, d, q)
1. n ← length [T]
2. m ← length [P]
3. h ← dm-1 mod q
4. p ← 0
5. t0 ← 0
QP23DP1_032 | 10-01-2023 15:13:03 | 117.55.241.162
6. for i ← 1 to m
7. do p ← (dp + P[i]) mod q
8. t0 ← (dt0+T [i]) mod q
9. for s ← 0 to n-m
10. do if p = ts
11. then if P [1.....m] = T [s+1.....s + m]
12. then "Pattern occurs with shift" s
13. If s < n-m
14. then ts+1 ← (d (ts-T [s+1]h)+T [s+m+1])mod q
Example: For string matching, working module q = 11, how many spurious hits does the Rabin-Karp
matcher encounters in Text T = 31415926535.......
1. T = 31415926535.......
2. P = 26
3. Here T.Length =11 so Q = 11
4. And P mod Q = 26 mod 11 = 4
5. Now find the exact match of P mod Q...
Solution:
The running time of RABIN-KARP-MATCHER in the worst case scenario O ((n-m+1) m but it
has a good average case running time. If the expected number of strong shifts is small O (1) and
Let us look at an example that describes the approximation algorithm for the set covering problem in
more detail
S1 = {1, 2, 3, 4} cost(S1) = 5
S2 = {2, 4, 5, 8, 10} cost(S2) = 10
S3 = {1, 3, 5, 7, 9, 11, 13} cost(S3) = 20
S4 = {4, 8, 12, 16, 20} cost(S4) = 12
S5 = {5, 6, 7, 8, 9} cost(S5) = 15
Step 1
The output set, Output = ф
Find the cost effectiveness of each set for no elements in the output set,
S1 = cost(S1) / (S1 – Output) = 5 / (4 – 0)
S2 = cost(S2) / (S2 – Output) = 10 / (5 – 0)
S3 = cost(S3) / (S3 – Output) = 20 / (7 – 0)
S4 = cost(S4) / (S4 – Output) = 12 / (5 – 0)
S5 = cost(S5) / (S5 – Output) = 15 / (5 – 0)
The minimum cost effectiveness in this iteration is achieved at S1, therefore, the subset added to the
output set, Output = {S1} with elements {1, 2, 3, 4}
Step 2
Find the cost effectiveness of each set for the new elements in the output set,
S2 = cost(S2) / (S2 – Output) = 10 / (5 – 4)
S3 = cost(S3) / (S3 – Output) = 20 / (7 – 4)
S4 = cost(S4) / (S4 – Output) = 12 / (5 – 4)