Yogita - IA of Analysis and Design of Algorithm
Yogita - IA of Analysis and Design of Algorithm
INTERNAL ASSIGNMENT
Consider a recursive implementation of the factorial function in a programming language like Python:
def factorial_recursive(n):
if n == 0 or n == 1:
return 1
else:
return n * factorial_recursive(n - 1)
Each recursive call to factorial_recursive adds a new stack frame to the call stack.
The stack frames are not released until the base case is reached, and the recursive calls start
returning.
The depth of the call stack corresponds to the level of recursion.
Analysis:
The recursive algorithm uses additional stack space proportional to the depth of recursion.
The space complexity is O(n), where n is the input to the factorial function.
Recursive algorithms may be susceptible to stack overflow if the recursion depth becomes too large.
def factorial_iterative(n):
result = 1
for i in range(1, n + 1):
result *= i
return result
The non-recursive algorithm does not rely on recursive calls and, therefore, does not create
additional stack frames.
The space complexity is O(1) as the space required is constant regardless of the input size.
Analysis:
The non-recursive algorithm is generally more memory-efficient compared to the recursive one.
It is not prone to stack overflow issues associated with deep recursion.
Comparison:
.
Space Complexity:
.
Recursive: O(n)
Non-Recursive: O(1)
.
Stack Space Utilization:
.
Recursive: Utilizes stack space proportional to the recursion depth.
Non-Recursive: Does not use additional stack space.
.
Risk of Stack Overflow:
.
Recursive: Risk of stack overflow for large input values due to the recursive call stack.
Non-Recursive: Lower risk of stack overflow as it doesn't rely on recursion.
.
Readability and Simplicity:
.
Recursive: Can be more intuitive and concise for certain algorithms but may sacrifice space
efficiency.
Non-Recursive: May involve more explicit control flow but is often more memory-efficient.
Q.1 As the head of the IT department at the university library, you have been presented
with a challenge. The library's current book search system has been identified as
inefficient—especially during peak hours when student traffic is high, resulting in slow
search response times. Considering that the library's database of book titles is sorted,
propose a search algorithm to expedite search times.
Ans. Given that the library's database of book titles is sorted, an efficient search algorithm to
expedite search times is the Binary Search algorithm. Binary Search is a divide-and-conquer
algorithm that quickly locates a target value within a sorted collection by repeatedly dividing the
search interval in half.
Initialization: Start with the entire sorted collection (in this case, the list of book titles).
.
Define Search Range: Identify the middle element of the current search range.
Compare with Target: Compare the middle element with the target value.
.
Adjust Search Range:
If the middle element is equal to the target, the search is successful.
If the target is less than the middle element, repeat the search on the left half of the collection.
If the target is greater than the middle element, repeat the search on the right half of the
collection.
.
Repeat: Repeat steps 2-4 until the target is found or the search range becomes empty.
.
Result: If the target is found, return its position in the collection; otherwise, indicate that the
target is not present.
Efficiency: Binary Search has a time complexity of O(log n), making it significantly faster than
linear search algorithms.
Optimal for Sorted Data: Since the library's database is already sorted, Binary Search is
particularly well-suited.
Replace the current search mechanism with Binary Search for book titles in the library's
database.
Ensure that the database remains sorted for the algorithm to work effectively.
Monitor and evaluate the search performance during peak hours to confirm improvements.
By implementing Binary Search, the library can significantly expedite search times, especially
during peak hours, leading to an improved and more efficient book search system fo
Ans. Performing BFS Traversal:
Start with vertex A: We'll visit A first as it's the starting point.
Q.2Traverse the following graph by Breadth First search and construct the
corresponding BFS tree. Start the traversal at vertex ‘a’ and name the
respective edges.
Exploring A's Neighbors:
Imagine you have a friend named A, and you want to visit their friends.
You start with A and visit all friends directly connected to A, like B, C, and D.
You prioritize visiting friends with shorter connections first, like B and C, before
going to D.
As you visit each friend, you mark them as visited so you don't go back to the
same friend later.
Now, think of this process as making a tree. A is the starting point, the root of the
tree.
Connect A to its visited friends (B, C, and D) because you visited them from A.
Continue connecting friends to their friends, like B to F, and C to E and G.
/ \
B C
/ /\
F E G
This tree shows the connection between friends. A is the starting point, and you
connect friends level by level, just like you visited them.
Additional Notes:
If friends have the same distance (connections of equal length), the order you
visit them might change.
BFS makes sure to finish visiting all friends at a certain level before moving to the
next level.
It's like exploring a social network, making sure you meet everyone at the same
level before moving on to the next group.
Imagine a table where each cell represents a specific scenario of choosing items
and staying within the weight limit.
We start filling in this table step by step.
For each item and each possible backpack weight, we decide whether it's better
to include the item or not based on the total value we can get.
We keep track of the best choices in the table.
We go through each item and each possible backpack weight, considering if it's
better to include the item or not.
We use the information from the previous row in the table to make these
decisions.
The goal is to find the best value we can get for each combination of items and
weights.
5. Example:
If our backpack can carry a maximum weight of 5 units, and we have items with
weights and values, the solution might tell us to pick specific items (like item 1, 3, and 4)
to get the maximum total value, which is 35.
In simple terms, we're solving a problem of choosing items to put in a backpack to get
the most value without making it too heavy.
Q.4 Solve the following Single Source Shortest path problem assuming a
suitable vertex and obtain its time efficiency.
Imagine you have a city (graph) with different places (vertices) and roads (edges)
connecting them, and you want to find the shortest path from one place (source) to all
others.
You start by creating a list of visited places (set S), a list to remember distances
(dist), and a priority queue (Q) to keep track of unvisited places.
While there are still places to visit in the priority queue (Q):
Pick the place (vertex) that is currently the closest to the source from the priority
queue.
Mark it as visited.
For each unvisited neighbor of that place:
Calculate the distance from the source to that neighbor through the
currently visited place.
If this new distance is shorter than the previously known distance to the
neighbor:
Update the distance to the shorter one.
If the neighbor is already in the priority queue, update its priority.
If not, add it to the priority queue.
After visiting all places, you have the shortest paths from the source to every
other place in the list called 'dist.'
4. Time Management:
The time it takes to do this depends on the number of places (vertices) and roads
(edges) in the city.
For this algorithm, it's effective when there are fewer roads compared to places.
Apply these steps to find the shortest paths from a starting place (vertex a) to all
other places in the graph.
The complexity of this process depends on how many places and roads are in the
graph.
In simple terms, Dijkstra's algorithm is like finding the best route through a city,
keeping track of distances and updating as you discover shorter paths. It works well
when there aren't too many roads to check.
.
Start in the leftmost column:
.
Begin in the first column and move one column at a time.
.
Place a queen in a safe spot:
.
Try placing a queen in the current column in a row where it won't conflict
with any previously placed queens.
.
Move to the next column:
.
Move to the next column and repeat steps 2 and 3.
.
Backtrack if needed:
.
If placing a queen in the current column leads to a conflict, go back to the
previous column and try a different row.
.
Repeat until solution found or all possibilities explored:
.
Keep going back and trying different placements until a solution is found
or all possibilities are explored.
return
This pseudocode outlines the basic steps of the N-Queens problem using backtracking.
It places queens one by one in different columns, making sure they don't threaten each
other. If a conflict is encountered, it backtracks to try a different path. This process
continues until a solution is found or all possibilities are explored.