Design of Algorithms Cat
Design of Algorithms Cat
1. Using a language of your choice write a pseudo code for insertion sort consisting of array
A with n item and use the array A [90, 4.65.100, 5]
Insertion Sort(A)
n = length(A)
for i = 1 to n-1 do
key = A[i]
j=i-1
A[j+1] = A[j]
j=j-1
end while
A[j+1] = key
end for
return A
end InsertionSort
// Example usage:
SortedA = InsertionSort(A)
print SortedA
This pseudo code represents the insertion sort algorithm. It starts by iterating through the array from
the second element (index 1) to the last element. At each iteration, it selects the current element as
the key and compares it with the elements before it. If any element is greater than the key, it shifts
the element to the right to make space for the key. This process continues until all elements are in
their sorted positions.
In the given example, the array [90, 4, 65, 100, 5] is passed to the Insertion Sort function, and the
sorted array is stored in Sorted A. Finally, the sorted array is printed.
1. Partition: The partition step divides the array into two parts based on a randomly chosen
pivot. The time complexity of this step is O(n) since we need to iterate through the entire
array to rearrange the elements around the pivot.
2. Recursion: After the partition step, the algorithm recursively calls itself on the two subarrays
formed. Let's assume that the length of the array is n. In the worst case, the pivot chosen
splits the array into two subarrays of sizes 1 and n-1. In the best case, the pivot results in two
subarrays of sizes (n/2) and (n/2). In the average case, we can assume that the split is
roughly balanced. Therefore, on average, the two recursive calls process subarrays of sizes
n/2.
3. Merge: After the recursive calls, the algorithm performs a merge step on the two subarrays.
The merge step takes time proportional to the product of the lengths of the two subarrays,
which is (n/2) * (n/2) = (n^2)/4.
Let T(n) represent the expected running time for an input array of size n. We can express this as
follows:
T(n) = Time for partition step + Time for recursive calls + Time for merge step
Using the Master Theorem for divide-and-conquer recurrence relations, we can determine that the
expected running time of the algorithm is O(n^2).
Therefore, the expected running time of the given algorithm is Cn^2 for some constant C.
3.
(a)There are n groups of people trying to schedule meetings at the same time, and there are m
meeting rooms available. Each group i (i = 1, 2, ..., n)
has ai people, and each room j (j = 1, 2, ..., m) has a capacity of bj . Group i can be scheduled to
use room j if and only if ai ≤ bj (i.e., the number of people is no larger than the capacity of the
room).
Of these n groups, the first k (1 ≤ k ≤ n) groups have high priority and they need to be
scheduled (there will always be at least one way to schedule them). Design an algorithm that
schedules all the high priority group, and schedules as many other groups as possible.
To schedule the high priority groups and as many other groups as possible, we can use a greedy
algorithm approach. Here's the algorithm:
Sort the groups in non-decreasing order of their number of people (ai) and assign a unique identifier
to each group.
Set two pointers: i to track the groups and j to track the meeting rooms, both starting at the beginning
(i = 1, j = 1).
If ai <= bj, schedule group i to use meeting room j, and increment both i and j.
The algorithm iterates through the groups and meeting rooms in a sorted order, ensuring that we
always consider the group with the lowest number of people and the meeting room with the lowest
capacity.
The running time of the algorithm is dominated by the sorting steps in the beginning. Sorting n
groups and m meeting rooms takes O(n log n + m log m) time. The remaining steps, including
iterating through the sorted lists, take O(n + m) time.
Therefore, the overall running time of the algorithm is O(n log n + m log m), as required.
4.Suppose you are given an m × m checkerboard and a checker. You are allowed to move the
checker from any square x to a square y on the board as long as square y is directly above
x, or y is directly to the left of the square directly above x, or y is directly to the right of
the square directly above x. Every time you make a move from square x to square y, you
earn p(x, y) points, where p(x, y) is an integer (possibly negative) that is part of the input.
Give an algorithm that on input the values p(x, y), outputs the maximum score that can be
achieved by placing the checker on some square on the bottom row and moving the checker
all the way to some square of the top row. The algorithm should run in polynomial time
Denote the maximum score that can be achieved by reaching square (i, j) as M(i, j). The goal is to
find the maximum score on the top row, which would be the maximum value among M(1, j) for all
valid j.
algorithm that solves the problem using dynamic programming:
2. Initialize the first row of M with the values of the bottom row of the input, i.e., M(m, j) = p(m, j)
for 1 ≤ j ≤ m.
3. Starting from the second-to-last row (row m-1) and moving upwards to the top row (row 1),
iterate over each square (i, j) on the current row.
a. Calculate the maximum score for reaching square (i, j) by considering the three possible moves
from the square directly below it (i+1, j) and selecting the move that gives the maximum score:
b. Update the maximum score for reaching square (i, j) in the M array.
4. Find the maximum value among M(1, j) for all valid j on the top row (row 1). This represents
the maximum score achievable by placing the checker on some square on the bottom row
and moving it all the way to the top row.