Design and Analysis of Algorithms __ 23CSH-282
Design and Analysis of Algorithms __ 23CSH-282
(23CSH-282)
Compiled by : Subhayu
Contents :
(Click on the Unit below, to skip to that particular unit)
Unit 1……………………………………………………………………………………………………………………………………..
Unit 2…………………………………………………………………………………………………………………………………….
Unit 3……………………………………………………………………………………………………………………………………..
MST 1 and 2 solutions………………………………………………………………………………………………………
Sample Questions…………………………………………………..…………………………………………………………..
UNIT-1 : Introduction to Algorithms
Contact Hours: 10
1. Analysis Framework
Analyzing an algorithm helps determine how efficient it is in terms of time and
space. The two main types of analysis are:
Most algorithms are analyzed based on the size of the input. As n increases, we
want to know how the algorithm’s performance changes.
● Worst Case: The maximum number of steps the algorithm takes for any
input of size n.
● Average Case: The expected number of steps over all possible inputs of size
n.
2. Asymptotic Notations
Asymptotic notations describe the growth of an algorithm's running time or
space as the input size becomes very large. These notations provide a high-level
understanding of an algorithm's efficiency.
● It tells us the average or expected time when lower and upper bounds are
the same.
● Example (Iterative):
for i in range(n):
print(i)
for j in range(n):
print(i, j)
Measures how much additional memory the algorithm uses based on input size.
● Example:
arr = [0] * n
● Space Complexity: O(n)
● Example:
def sum_n(n):
total = 0
total += i
return total
Time complexity depends on the number of recursive calls and the work done in
each call.
● Example:
def factorial(n):
if n == 0:
return 1
return n * factorial(n-1)
5. Recurrence Relations
A recurrence relation expresses the time complexity of a recursive function in
terms of the time complexity of smaller inputs.
Used to guess the form of the solution and prove it using mathematical
induction.
● Example: Given:
T(n) = T(n-1) + n
T(1) = 1
● Try:
T(n) = O(n²)
● Use induction to prove this guess.
Used to visualize the recurrence relation by drawing a tree showing how the input
is broken down at each level.
● Example:
T(n) = 2T(n/2) + n
● Each level does n work. Tree has log n levels → Total = n log n
Where:
● a ≥ 1 and b > 1
● f(n) is a function of n
Example:
log_b a = log₂2 = 1
Summary Table:
Definition:
The Divide and Conquer strategy breaks a problem into smaller sub-problems,
solves each recursively, and then combines the results to form the solution to the
original problem.
Steps:
3. Combine: Merge the results of the sub-problems to get the final answer.
Instead of comparing all elements linearly, the array is divided into halves and
minimum/maximum is found recursively.
Algorithm (High-Level):
● If more than two: divide into halves, find min/max of each, then compare
results.
Time Complexity:
Code Outline:
def merge_sort(arr):
if len(arr) <= 1:
return arr
mid = len(arr)//2
left = merge_sort(arr[:mid])
right = merge_sort(arr[mid:])
return merge(left, right)
Code Outline:
def quick_sort(arr):
if len(arr) <= 1:
return arr
pivot = arr[0]
less = [x for x in arr[1:] if x <= pivot]
more = [x for x in arr[1:] if x > pivot]
return quick_sort(less) + [pivot] + quick_sort(more)
Time Complexity:
Steps:
Time Complexity:
In-Place: Yes
Stable: No
Time Complexity:
Code Outline:
def binary_search(arr, target):
low, high = 0, len(arr)-1
while low <= high:
mid = (low + high)//2
if arr[mid] == target:
return mid
elif arr[mid] < target:
low = mid + 1
else:
high = mid - 1
return -1
Time Complexity: O(log n)
Idea:
Time Complexity:
● Worst: O(n^2)
Approach:
Definition:
Key Characteristics:
● Works in stages.
● No backtracking.
Problem Statement:
Given:
Maximize the total value in the knapsack. Items can be broken (fractions
allowed).
Greedy Strategy:
● Pick as much as possible from the item with the highest ratio.
Steps:
Problem Statement:
● profit[i]
Each job takes one unit of time, and only one job can be scheduled at a time.
Maximize total profit by selecting jobs within their deadlines.
Greedy Strategy:
● For each job, try to assign it to the latest available time slot before or on
its deadline.
Steps:
4. Huffman Coding
Problem Statement:
Given characters with their frequencies, build a binary prefix code (no code is
prefix of another) that minimizes the total encoded length.
Greedy Strategy:
● Combine the two least frequent characters repeatedly into a new node.
Steps:
Idea:
Idea:
Start from any vertex and repeatedly add the smallest edge that connects a new
vertex to the growing MST.
Steps:
Time Complexity:
Problem Statement:
Given n activities with start[i] and finish[i], select the maximum number of
non-overlapping activities.
Greedy Strategy:
Always pick the next activity that finishes earliest, among the remaining ones.
Steps:
○ If its start time ≥ finish time of last selected activity, select it.
Summary Table:
Problem Strategy Time Complexity
Problem:
Items:
Solution:
Calculate value/weight:
● Item 1: 60 / 10 = 6
● Item 2: 100 / 20 = 5
● Item 3: 120 / 30 = 4
Steps:
● Job A: 2, 100
● Job B: 1, 19
● Job C: 2, 27
● Job D: 1, 25
● Job E: 3, 15
Solution:
● A → Slot 2 (available) ✅
● C → Slot 1 (available) ✅
● B → Slot 3 (available) ✅
3. Huffman Coding
Problem:
● A: 5
● B: 9
● C: 12
● D: 13
● E: 16
● F: 45
● F: 0
● C: 100
● D: 101
● A: 1100
● B: 1101
● E: 111
Problem:
mathematica
CopyEdit
A-B: 1
B-C: 4
A-C: 3
C-D: 2
D-E: 5
E-A: 6
Solution:
● A-B
● C-D
● A-C
● D-E
5. Prim’s Algorithm
Step-by-step selection:
● A → B (1)
● Now C → D (2)
● D → E (5)
Problem:
A1 1 3
A2 2 5
A3 4 6
A4 6 7
A5 5 8
A6 8 9
Solution:
● The problem has optimal substructure (solution to the problem can be built
from optimal solutions of subproblems).
Problem:
Given weights and values of n items, put these items in a knapsack of capacity W
such that total value is maximized, and you cannot break items (0 or 1 of each).
Steps:
2. dp[i][j] = Maximum value for first i items and capacity j.
3. Initialization:
4. For each item i from 1 to n, and for each capacity j:
○ Else:
dp[i][j] = dp[i-1][j]
Problem:
Given two strings, find the length of their longest subsequence that appears in
both.
Steps:
○ If characters match:
dp[i][j] = dp[i-1][j-1] + 1
○ Else:
dp[i][j] = max(dp[i-1][j], dp[i][j-1])
Problem:
Given a set of cities and distances between each pair, find the shortest tour that
visits all cities and returns to the start.
2. Define dp[mask][i] as the minimum cost to reach city i having visited cities
in mask.
4.
5. Final answer: min(dp[all_visited][i] + dist[i][0]) for all i
4. Bellman-Ford Algorithm
Problem:
Find the shortest path from a single source to all vertices, even with negative edge
weights (no negative cycle).
Steps:
5. Floyd-Warshall Algorithm
Problem:
Steps:
2.
3. Repeat for all i, j, and k.
Problem:
Given keys with access probabilities, build a BST with minimum expected search
cost.
Steps:
Problem:
Given coin denominations and a total amount, find the number of ways to make
the amount using any number of coins.
Steps:
This version counts the number of combinations. A variation gives the minimum
number of coins using a similar table.
Given dimensions of matrices, find the most efficient way to multiply them.
Steps:
Problem:
Items:
Weights = [1, 3, 4, 5]
Values = [10, 40, 50, 70]
Knapsack Capacity = 8
Solution:
Create a dp table where dp[i][w] is the max value for first i items and capacity
w.
Problem:
X = "AGGTAB"
Y = "GXTXAYB"
Solution:
LCS = "GTAB"
Problem:
0 1 2 3
-------------
0 | 0 10 15 20
1 | 10 0 35 25
2 | 15 35 0 30
3 | 20 25 30 0
Solution:
4. Bellman-Ford Algorithm
Problem:
Vertices = 5, source = 0
Edges:
0 → 1 (6)
0 → 2 (7)
1 → 2 (8)
1 → 3 (5)
1 → 4 (-4)
2 → 3 (-3)
2 → 4 (9)
3 → 1 (-2)
4 → 3 (7)
4 → 0 (2)
Result:
5. Floyd-Warshall Algorithm
Problem:
Graph:
A → B (3)
A → C (8)
B → C (2)
B → D (5)
C → D (1)
D → A (2)
Result:
Problem:
Result:
Problem:
Solution:
Number of ways = 4
Ways:
(1+1+1+1), (1+1+2), (2+2), (1+3)
8. Matrix Chain Multiplication
Problem:
Solution:
Chapter 5: Backtracking
1. Introduction to Backtracking
Backtracking is a systematic method of trying out different sequences of
decisions until a solution is found.
● If a path does not lead to a solution, it "backtracks" and tries the next
alternative.
def backtrack(state):
if is_solution(state):
process_solution(state)
else:
for choice in valid_choices(state):
make_choice(choice)
backtrack(new_state)
undo_choice(choice)
Recursive Backtracking
● The backtracking logic is implemented using function recursion.
Iterative Backtracking
3. N-Queens Problem
Problem:
Constraints:
Approach:
Key Function:
● is_safe(row, col) checks if placing a queen is valid.
4. Hamiltonian Cycle
Problem:
Find a cycle that visits each vertex of a graph exactly once and returns to the
starting point.
Input:
Approach:
Constraints:
● A valid vertex must be adjacent to the last vertex in the path and not
already visited.
Problem:
Move a knight on a chessboard such that it visits every square exactly once.
Approach:
● Use recursion to try all 8 possible knight moves from the current position.
Steps:
3. If no move is possible and not all squares are visited, backtrack.
Problem:
Color the vertices of a graph using at most m colors such that no two adjacent
vertices have the same color.
Approach:
Example:
Hamiltonian Visit each vertex once and return to Valid edge, unvisited
Cycle start
Knight's Tour Visit each cell once with knight's Board bounds,
move unvisited
Problem:
Place 4 queens on a 4×4 board so that no two queens attack each other.
Solution Idea:
We fill the board row by row, placing one queen per row.
Steps:
● Final Solution:
. Q . .
. . . Q
Q . . .
. . Q .
Graph:
Vertices: A, B, C, D
Adjacency Matrix:
A B C D
A [ 0 1 1 1 ]
B [ 1 0 1 0 ]
C [ 1 1 0 1 ]
D [ 1 0 1 0 ]
Find a cycle:
Start at A → B → C → D → A
● All vertices visited exactly once, and final edge D→A exists.
Goal:
Start Position:
(0, 0)
Example Steps:
1. (0,0)
2. (2,1)
3. (3,3)
4. (1,2) ...continue backtracking until the knight covers all cells.
This is a trial-and-error approach where invalid moves are discarded, and the
algorithm backtracks.
Graph:
● 4 Vertices: A, B, C, D
● Max colors = 3
Goal:
Steps:
Coloring:
● A → 1
● B → 2
● C → 3
● D → 1
5. Lower-Bound Theory Example (TSP context)
A B C D
A 0 10 15 20
B 10 0 35 25
C 15 35 0 30
D 20 25 30 0
Partial path: A → B → C
● D to A = 20
● 0/1 Knapsack
● Assignment Problems
Basic Concepts:
● Nodes are expanded in the order they were added to the queue.
● Uses a priority queue, where nodes with lowest cost (bound) are given
priority.
● Useful when we can calculate a cost function or lower bound for nodes.
Problem Statement:
Given weights and values of n items, put these items in a knapsack of capacity W
to get the maximum total value, where you can either include or exclude an item
(0/1 only).
B. Bounding Function:
Estimate the upper bound of maximum profit starting from the current node.
○ If this node’s weight is within limit and profit is higher than current
max, update max.
This guarantees that all possibilities are explored, but may not be optimal in
speed.
5. LC Branch and Bound for 0/1 Knapsack
(Steps)
1. Use a priority queue ordered by maximum bound (i.e., most promising
solution).
Prunes more paths than FIFO, thus faster and more efficient.
Items:
● Knapsack Capacity = 5
Steps (simplified):
4. Continue branching, update max when weight ≤ 5 and profit > previous
max.
5. Use fractional value for bounding estimate when exceeding weight.
Limitations
● Still exponential in worst case.
Problem:
● Items:
3. Keep checking which combinations stay within capacity and give higher
profit.
● Items:
● Capacity = 5
3. Continue branching and pruning nodes with bound ≤ current max profit.
Definition:
In other words:
Examples:
● Binary Search
● Merge Sort
● Dijkstra’s Algorithm
Key point:
Examples:
● Sudoku
● Hamiltonian Path
● Subset Sum
If someone gives you a solution to any of these, you can check it quickly. But
finding it may take exponential time.
Deterministic Algorithm:
Non-Deterministic Algorithm:
5. NP-Complete Problems
Definition:
These are the "hardest" problems in NP. If one NPC problem is solved in
polynomial time, then P = NP.
Examples:
● Hamiltonian Cycle
● 3-SAT
6. NP-Hard Problems
Definition:
Examples:
● Halting Problem
● Scheduling problems
Diagrammatically:
css
CopyEdit
P ⊆ NP
NP-Complete ⊆ NP
NP-Hard ⊄ NP (in general)
9. Practical Implications
● If a problem is in P, we can solve it efficiently.
Example Comparisons
Problem Class Notes
Solutions/Answers :
● Worst-case:
This represents the maximum time or space an algorithm may take on
any input of size n. It shows the algorithm’s upper bound.
● Best-case:
This represents the minimum time or space required. It occurs under ideal
conditions.
○ Example: In linear search, if the element is at the first position →
O(1).
● Average-case:
This reflects the expected performance over all possible inputs. It provides
a realistic efficiency estimate.
1. Guess the form of the solution (e.g., T(n) = O(n log n)).
3. Base case: Verify that the recurrence holds true for the smallest input (e.g.,
n = 1).
4. Inductive step: Assume it holds for n = k and prove it for n = k+1.
5. Conclude the function’s time complexity based on the final inequality.
Significance:
● Used in task scheduling, where some tasks must be done before others
(e.g., course prerequisites).
Example:
Tasks: A → B → C
Topological Order: A, B, C
2. Using the solution of the smaller instance to build the final answer.
Types:
Example:
Binary Search:
Steps:
A = [[1,2],[3,4]]
B = [[5,6],[7,8]]
Let:
A = [[a,b],[c,d]] = [[1,2],[3,4]]
B = [[e,f],[g,h]] = [[5,6],[7,8]]
M1 =(a+d)(e+h) =(1+4)(5+8)=5×13 = 65
M2 =(c+d)e =(3+4)×5=7×5 = 35
M3 =a(f−h) =1×(6−8)=1×(−2) = −2
M4 =d(g−e) =4×(7−5)=4×2 = 8
M5 =(a+b)h =(1+2)×8=3×8 = 24
M6 =(c−a)(e+f) =(3−1)×(5+6)=2×11 = 22
M7 =(b−d)(g+h) =(2−4)×(7+8)=(−2)×15 = −30
Final Result:
C = [[19,22],[43,50]]
Example DAG:
● A → B
● A → C
● B → D
● C → D
Graphically:
A
/ \
B C
\ /
D
1. Find all vertices with in-degree 0 and add them to a queue.
2. Remove one vertex from the queue, add it to the topological order.
3. For each neighbor of that vertex, decrease its in-degree by 1.
● In-degrees:
○ A: 0, B: 1, C: 1, D: 2
● Choose B → Output: A, B
● Choose C → Output: A, B, C
● Choose D → Output: A, B, C, D
Solutions/Answers :
Efficiency Easier and faster (O(n log n) due Requires dynamic programming
to sorting) or backtracking
Example If you can’t take the whole item, If you can’t take the whole
you can take a part of it item, you take nothing
Problem Continuous Discrete
Type
Character Frequency
A 5
B 9
C 12
D 13
E 16
F 45
Character Code
A 1100
B 1101
C 100
D 101
E 111
F 0
○ Contains no cycles
○ Has the minimum possible total edge weight
● Prim’s Algorithm: Builds the MST by adding the least costly edge from a
node already in the tree.
Applications:
● Circuit design
Item Items can be divided. You Items cannot be divided. You either
Selection can take fractions of an take the whole item or none.
item.
Matrix Chain Multiplication problem is not about multiplying matrices but finding
the most efficient way (i.e., minimum number of scalar multiplications) to
multiply a given chain of matrices.
Problem Setup:
Key Concepts:
● Matrix multiplication is associative, but the order of multiplication affects
the total computation.
Steps in Algorithm:
1. Let m[i][j] represent the minimum number of scalar multiplications needed
to compute the matrix product Ai...Aj.
2. Let s[i][j] store the index at which the optimal split occurs.
○ For i = 1 to n−L+1:
■ Set j = i + L − 1
■ Set m[i][j] = ∞
■ For k = i to j−1:
Example:
Possible parenthesizations:
5. State the difference between a Hamiltonian path and an Euler path.
9. Mention the difference between FIFO and LC branch and bound approaches.
11. What is the main idea behind the concept of a deterministic algorithm?
2. Explain the working of FIFO Branch and Bound using a binary tree
structure.
3. Differentiate between P, NP, NP-Hard and NP-Complete problems with
examples.
4. Solve a simple instance of the Knight’s Tour problem using backtracking for
a 5×5 board.
6. Illustrate the use of backtracking to solve a graph coloring problem with 3
colors and 4 nodes.
2. Implement the Hamiltonian Cycle problem for a given undirected graph
using backtracking.
3. Solve the 0/1 Knapsack problem using Least Cost Branch and Bound, and
explain the pruning strategy used.
4. Discuss in detail the difference between FIFO and LC (Least Cost) Branch
and Bound methods with respect to a Knapsack instance.
5. Prove that SAT is NP-Complete. Briefly explain the implications of this
classification in computational complexity.