MCS-211 Design and Analysis of Algorithms
MCS-211 Design and Analysis of Algorithms
(a) Design and develop an efficient algorithm to find the list of prime
numbers in the range 501 to 2000. What is the complexity of this algorithm?
Sieve of Eratosthenes can be used to efficiently find prime numbers in the given
range.
Algorithm:
Complexity:
● Definition: The time complexity grows proportionally to the cube of the input size.
● Example: Matrix Multiplication (naive algorithm)
● Definition: The time complexity grows proportionally to the factorial of the input
size, making it extremely slow for large inputs.
● Example: Solving the Traveling Salesman Problem (using brute-force search)
The key difference between these two is that the Cubic-time algorithms are
polynomial-time and feasible for moderate inputs, while factorial-time algorithms are
exponential-time and impractical for large inputs.
(c) Write an algorithm to multiply two square matrices of order n*n. Also,
explain the time complexity of this algorithm.
Algorithm:
● Initialize a result matrix CC of size n×nn \times n with all elements set to 0.
● For each element C[i][j]C[i][j] in the result matrix:
○ Compute the sum of the products A[i][k]⋅B[k][j]A[i][k] \cdot B[k][j] for all kk
from 0 to n−1n-1.
● Return the result matrix CC.
Time Complexity
The time complexity of this algorithm is O(n^3). This is because there are three nested
loops, each iterating over the size n of the matrices. For each pair of elements
C[i][j]C[i][j], we perform n multiplications and additions.
Big O-notation
It is used to describe the asymptotic upper bound of an algorithm, i.e. its worst-case
scenario.An algorithm with a running time of f(n) is equivalent to O(g(n)) if and only if
there are constants c and n0 such that the below expression is satisfied along with its
graph below.
Big Θ-notation
This notation describes both the upper and lower bound of a function and is often
referred to as the average time complexity. Big-Theta notation is described
mathematically as follows which can be visualised in the graph below.
Big O and Θ Notation for the function 𝑓(𝑛)= 100𝑛4 +1000𝑛3 +100000
● Dominant term is 𝑛4
● Big O: O(𝑛4)
● Big Θ: Θ(𝑛4)
(e) Write and explain the Left to Right binary exponentiation algorithm.
Demonstrate the use of this algorithm to compute the value of 329 (Show
the steps of computation). Explain the worst-case complexity of this
algorithm.
Algorithm:
● Convert the exponent b to its binary representation.
● Initialize the result res=1.
● Iterate through each bit of b from left (most significant bit) to right (least
significant bit):
○ Square the result: res=res×res
○ If the current bit is 1, multiply the result by a: res=res×a.
● Return the final result res.
Steps for computing 329
Step 1: Binary Representation of 29
● 29 in binary: 11101
Step 2: Initialize
● res=1
● Bit 1:
○ Square: res=3×3=9
○ Multiply by a (since bit is 1): res=9×3=27
● Bit 1:
○ Square: res=27×27=729
○ Multiply by a (since bit is 1): res=729×3=2187
● Bit 0:
○ Square: res = 2187 × 2187 = 4782969
○ Do not multiply by a (since bit is 0)
● Bit 1 (Rightmost):
○ Square: res = 4782969 × 4782969 = 22876792454961
○ Multiply by a (since bit is 1 ): res = 2287679245496 1 × 3 =
68630377364883
● Final Result:
○ 329 = 68630377364883
Worst-Case Complexity
● The algorithm processes each bit of the exponent b.
● For an exponent b with k bits:
○ It performs k squaring operations.
○ It performs at most k multiplications (one for each bit that is 1).
● Thus, the total number of operations is O(logb).
(f) Write and explain the Bubble sort algorithm. Discuss its best and
worst-case time complexity.
Algorithm Steps:
● Initialize: Start from the first element.
● Compare and Swap: Compare each pair of adjacent elements. If the first element
is greater than the second, swap them.
● Repeat: Move to the next pair of adjacent elements and repeat the comparison
and swap process.
● Iterate: Continue this process for multiple passes through the list until no swaps
are needed.
Time Complexity:
Worst-case O(n²) Occurs when the array is in reverse order, requiring maximum
swaps.
Best-case O(n) If the array is already sorted, the algorithm exits early
(optimized version).
Bubble Sort is not the most efficient algorithm for large datasets, but its simplicity makes
it useful for small datasets or educational purposes.
(g) What are the uses of recurrence relations? Solve the following
recurrence relations using the Master’s method
𝑛
(I) 𝑇(𝑛) = 4𝑇 ( 4 ) + 𝑛1
3𝑛
(II) 𝑇(𝑛) = 4𝑇 ( 4
) + 𝑛1
Master’s Theorem
𝑛
(I) Solving: 𝑇(𝑛) = 4𝑇( 4 )+𝑛1
An optimization problem involves finding the best solution from a set of possible
solutions, given certain constraints. The goal is to either maximize or minimize a
particular objective function.
Example:
Greedy Approach
When to Use:
● When a problem has an optimal substructure (an optimal solution to the problem
contains optimal solutions to subproblems).
● When a problem exhibits the Greedy-choice property (a global optimum can be
reached by choosing the local optimum).
Given data:
● Capacity = 20 Kg
● Profits (p): (30, 16, 18, 20, 10, 7)
● Weights (w): (5, 4, 6, 4, 5, 7)
● Profit/Weight Ratio: (30/5, 16/4, 18/6, 20/4, 10/5, 7/7) = (6,4,3,5,2,1)
Steps:
● Sort items by highest p/w ratio:
(p1
,p4,p2,p3,p5,p6)=(30,20,16,18,10,7)
● Add items until knapsack is full:
p1(6) 5 kg 30
p2 (5) 4 kg 20
p3(4) 4 kg 16
p4(3) 6 kg 18
Symbol Frequency
a 5
f 7
e 8
c 10
d 15
b 25
g 30
Symbol Frequency
e 8
c 10
(a,f) 12
d 15
b 25
g 30
● Step 2:
○ Combine e (8) and c (10).
○ Create a new node (e,c) with frequency 18.
○ Insert (e,c) back into the queue.
Symbol Frequency
(a,f) 12
d 15
(e.c) 18
b 25
g 30
● Step 3:
○ Combine (a,f) (12) and d (15).
○ Create a new node (a,f,d) with frequency 27.
○ Insert (a,f,d) back into the queue.
Symbol Frequency
(e,c) 18
b 25
(a,f,d) 27
g 30
● Step 4:
○ Combine (e,c) (18) and b (25).
○ Create a new node (e,c,b) with frequency 43.
○ Insert (e,c,b) back into the queue.
Symbol Frequency
(a,f,d) 27
g 30
(e.c.b) 43
● Step 5:
○ Combine (a,f,d) (27) and g (30).
○ Create a new node (a,f,d,g) with frequency 57.
○ Insert (a,f,d,g) back into the queue.
Symbol Frequency
(e,c,b) 43
(a,f,d,g) 57
● Final Step:
○ Combine (e,c,b) (43) and (a,f,d,g) (57).
○ Create the root node (a,b,c,d,e,f,g) with frequency 100.
Now, we'll traverse the tree to assign binary codes to each character. We'll use:
● Left Edge: 0
● Right Edge: 1
1. Start from the Root:
a 1000
b 01
c 001
d 101
e 000
f 1001
g 11
Step-by-Step Decoding:
● Third Symbol:
○ Bits: 1 0 0 0
○ Path: 1 0 0 0
○ Matches a
○ Decoded Symbol: a
Remaining Sequence: 01
● Fourth Symbol:
○ Bits: 0 1
○ Path: 0 1
○ Matches b
○ Decoded Symbol: b
The Merge procedure is a key part of the Merge Sort algorithm. It combines two sorted
subarrays into a single sorted array. It works as follows:
1. Divide:
○ Split the array into two halves recursively.
2. Sort:
○ Recursively sort each half.
3. Merge:
○ Use the Merge procedure to combine the two sorted halves.
Step-by-Step Merge Sort for Given Array
Input Array:
[19, 18, 16, 12, 11, 10, 9, 8]
Update subarrays:
Left: [18, 19] and [12, 16]
Right: [10, 11] and [8, 9]
● Merge [18, 19] and [12, 16] → [12, 16, 18, 19]
● Merge [10, 11] and [8, 9] → [8, 9, 10, 11]
● Final Merge:
○ Merge [12, 16, 18, 19] and [8, 9, 10, 11]
○ Compare and arrange elements.
Final Sorted Array: [8, 9, 10, 11, 12, 16, 18, 19]
Complexity of Merge Sort
Final Complexity:
(d) Explain the divide and conquer approach of multiplying two large
integers. Compute the time complexity of this approach. Also, explain the
binary search algorithm and find its time complexity.
The Divide and Conquer method for multiplication is an efficient way to multiply large
integers by breaking the problem into smaller subproblems and combining the results. A
famous example is Karatsuba’s Algorithm.
1. Divide:
Given two large numbers XXX and YYY, split them into two halves:
● Let X=10mA+B
● Let Y=10mC+D
For traditional multiplication of two n-digit numbers, the time complexity is O(n²).
T(n)=T(n/2)+O(1)
(e) Explain the Topological sorting with the help of an example. Also,
explain the algorithm of finding strongly connected components in a
directed Graph.
Example:
Execution
Steps:
Example:
1→2
2→3
3→1
3→4
4→5
5→4
● DFS completes 1 → 2 → 3 → 4 → 5.
● Stack after DFS: [3, 1, 2, 5, 4].
Final Output:
Conclusion
a) Write the Prim’s algorithm to find the minimum cost spanning tree of a
graph. Also, find the time complexity of Prim’s algorithm. Demonstrate the
use of Kruskal’s algorithm and Prim’s algorithm to find the minimum cost
spanning tree for the Graph given in Figure 1. Show all the steps.
> Prim’s Algorithm
1. Initialize:
● Select any arbitrary node as the starting node.
● Create an empty MST set.
● Maintain a priority queue (or min heap) for selecting the
minimum-weight edge.
Edge Weight
A→B 10
A→E 15
B→C 20
B→D 4
C→D 8
C→G 16
D→F 7
E→F 6
F→G 5
● Start with A.
● Choose the smallest edge: A → B (10).
● Add B to MST. Smallest edge from B: B → D (4).
● Add D. Smallest edge: D → F (7).
● Add F. Smallest edge: F → G (5).
● Add G. Smallest edge: C → D (8).
● Add C. Smallest edge: E → F (6).
● Add E.
A → B (10)
B → D (4)
D → F (7)
F → G (5)
C → D (8)
E → F (6)
Total MST cost: 40
Algorithm:
Edge Weight
B→D 4
F→G 5
E→F 6
D→F 7
C→D 8
A→B 10
C→G 16
A→E 15
B→C 20
● B → D (4)
● F → G (5)
● E → F (6)
● D → F (7)
● C → D (8)
● A → B (10)
B → D (4)
F → G (5)
E → F (6)
D → F (7)
C → D (8)
A → B (10)
(b) Write the Dijkstra’s shortest path algorithm. Also, find the time
complexity of this shortest path algorithm. Find the shortest paths
from the vertex ‘A’ using Dijkstra’s shortest path algorithm for the
graph given in Figure 1. Show all the steps of computation.
1. Initialize:
● Set the distance of the starting vertex to 0 and all others to ∞.
● Use a priority queue (min-heap) to select the vertex with the smallest
distance.
2. Relax Edges:
● Pick the vertex u with the smallest distance.
● Update distances for all adjacent vertices v if: d[v]>d[u] + w(u,v)
● Push updated vertices into the priority queue.
3. Repeat Until All Nodes Are Processed.
Time Complexity
● Using a priority queue (Min-Heap + Adjacency List): O((V + E) log V)
● Using an adjacency matrix: O(V²)
Step 1: Initialization
A: 0, B: ∞, C: ∞, D: ∞, E: ∞, F: ∞, G: ∞
● B → D (10 + 4 = 14)
● B → C (10 + 20 = 30)
● D → F (14 + 7 = 21)
● D → C (min(30, 14+8) = 22)
A 0 A
B 10 A→B
C 22 A→B→D→C
D 14 A→B→D
E 15 A→E
F 21 A→B→D→F
G 26 A→B→D→F→G
Conclusion
(c) Explain the algorithm to find the optimal Binary Search Tree.
Demonstrate this algorithm to find the Optimal Binary Search Tree for
the following probability data (where pi represents the probability that
the search will be for the key node ki, whereas qi represents that the
search is for dummy node di. Make suitable assumptions, if any)
i 0 1 2 3 4
The Optimal Binary Search Tree (OBST) minimizes the expected search cost by
arranging the keys in a way that reduces the weighted path length. This is done using
dynamic programming.
Step-by-Step Algorithm:
1. Input:
● Probabilities pifor searching keys ki
● Probabilities qifor searching dummy nodes di
2. Define Matrices:
● Cost Matrix C[i][j] → Minimum cost for searching between keys
ki to kj
● Weight Matrix W[i][j] → Sum of all p and q values in the range.
● Root Matrix R[i][j] → Stores the root of the subtree.
3. Initialization:
● C[i][i] = qifor dummy nodes.
● W[i][i] = qifor dummy nodes.
i 0 1 2 3 4
For example:
C[i][i] = qi
Using the R matrix, determine which keys should be the root of each subtree.
Time Complexity
Matrix Dimension
A1 10 x 15
A2 15 x 5
A3 5 x 20
A4 20 x 10
We have matrices:
● A1: 10×15
● A2: 15×5
● A3: 5×20
● A4: 20×10
Step 1: Define Dimensions
Array: p=[10,15,5,20,10]
(A1×(A2×A3))×A4
Therefore,
(e) Explain the Rabin Karp algorithm for string matching with the help
of an example. Find the time complexity of this algorithm.
1. Compute the hash value of the pattern and the first window of text.
2. Slide the window over the text one character at a time:
○ If the hash values match, do a character-by-character check.
○ If they don't match, slide to the next position and update the hash
efficiently.
3. Repeat until the end of the text.
Example
Text: "ABCDABCD"
Pattern: "BCD"
Using a simple hash function H:
Time Complexity
This makes Rabin-Karp efficient for multiple pattern searches in large texts.
Q4. a) Explain the term Decision problem with the help of an example.
Define the following problems and identify if they are decision
problem or optimization problem? Give reasons in support of your
answer.
(i) Travelling Salesman Problem
(ii) Graph Colouring Problem
(iii) 0-1 Knapsack Problem
A decision problem is a problem that can be posed as a yes/no question regarding the
existence of a solution that satisfies given constraints. In other words, it asks whether a
certain condition or property is true or false.
Example:
● Problem: Is there a path in a graph that visits each vertex exactly once and
returns to the starting point?
● Yes/No Question: Does a Hamiltonian cycle exist in the given graph?
Decision problems are often used in computational theory and algorithm design to
determine the feasibility of certain solutions before tackling optimization problems.
● Definition: Given a set of cities and distances between them, find the shortest
possible route that visits each city exactly once and returns to the starting point.
● Type: Optimisation Problem
● Reason: The goal is to find the shortest route, not just to check if a route exists.
● Definition: Given a graph and a number k, can the graph be coloured using k
colours such that no two adjacent vertices have the same colour?
● Type: Decision Problem
● Reason: The answer is either "Yes" (if the graph can be coloured with k colours)
or "No" (if it cannot be coloured with k colours).
● Definition: Given items with weights and values, and a knapsack of limited
capacity, determine the maximum value that can be obtained without exceeding
the capacity.
● Type: Optimisation Problem
● Reason: The goal is to maximise the total value rather than just answering a
yes/no question.
(b) What are P and NP class of Problems? Explain each class with the
help of at least two examples.
P-Class Problems
P (Polynomial time) class problems are those problems that can be solved by a
deterministic algorithm in polynomial time. In simpler terms, if a problem belongs to
class P, there exists an algorithm that can solve the problem in a reasonable amount of
time as the input size grows. These problems are considered efficiently solvable.
Examples:
NP-Class Problems
NP (Nondeterministic Polynomial time) class problems are those problems for which a
given solution can be verified in polynomial time by a deterministic algorithm. In other
words, if you are given a potential solution to an NP problem, you can quickly check if it
is correct. However, finding the solution from scratch may not be possible in polynomial
time. NP problems are not necessarily efficiently solvable, but their solutions can be
verified efficiently.
Examples:
Aspect N NP
(c) Define the NP-Hard and NP-Complete problem. How are they
different from each other? Explain the use of polynomial time
reduction with the help of an example.
> Differences
Example
1. 3-SAT is a decision problem where we check if a boolean formula in CNF can be
satisfied.
2. We can reduce any instance of 3-SAT to the Clique Problem in polynomial time
by constructing a graph such that finding a clique of a specific size corresponds
to satisfying the formula.
3. Since 3-SAT is NP-Complete, and we reduced it to Clique, Clique is also
NP-Hard.
This method helps in proving problems are NP-Hard or NP-Complete.
(a) SAT Problem (Boolean Satisfiability Problem)
Definition: The SAT problem is the first problem that was proven to be NP-Complete. It
asks whether there exists an assignment of truth values (true or false) to the variables
of a Boolean formula such that the formula evaluates to true.
Definition: The Clique problem asks whether there exists a subset of vertices in a given
graph such that every pair of vertices in the subset is connected by an edge, and the
size of the subset (clique) is at least kk.
Definition: The Hamiltonian Cycle problem asks whether there exists a cycle in a given
graph that visits each vertex exactly once and returns to the starting vertex.
Definition: The Subset Sum problem asks whether there exists a subset of a given set
of integers such that the sum of the subset is equal to a given target value.