q1 Soln
q1 Soln
q1 Soln
Instructions.
a. The exam is closed-book and closed-notes. You may not have your cell phone on your person.
b. You may use algorithms done in the class as subroutines and cite their properties.
c. Describe your algorithms completely and precisely in English, preferably using pseudo-code.
d. Grading will be based also on the justification given and on the clarity of your arguments. Always
argue correctness of your algorithms and analyze them.
Problem 1.
2 k
T (n) = T (n1/2 ) + 1 = T (n1/2 ) + 2 = · · · = T (n1/2 ) + k
1 1 log n
Setting, k = log(log(n)), T (n 2k ) = T (n log n ) = T (2 log n ) = T (2) = Θ(1). Hence, T (n) = log log n +
Θ(1). (All logs are to base 2).
c. Suppose A is an array with n elements that forms a min-heap, that is, A[Parent(i)] ≤ A[i], for all
i = 2, 3, . . . , n. Give an O(n) time procedure to convert A to a max-heap. (3)
Just use Build-Max-Heap(A, n) which runs in time Θ(n).
d. Let ωn be the primitive nth root of unity. Let a = (a0 , . . . , an−1 ) be an n-dimensional vector of
kj
complex numbers. Let yj = n−1
P
k=0 ak ωn , j = 0, 1, . . . , n − 1. Simplify the following expression in
terms of the aj ’s.
n−1
X
bm = yl ωnl(m+c) , m = 0, 1, . . . , n − 1
l=0
where, c is a fixed constant in {0, 1, . . . , n − 1}. (16)
n−1
X
bm = yl ωnl(m+c)
l=0
n−1
X n−1
X
= ak ωnkl ωnl(m+c)
l=0 k=0
n−1
X n−1 X
= ak ωnl(k+(m+c))
k=0 l=0
1
Consider the inner summation, for a fixed value of k. If k = −(m + c), the inner summation is n.
If k 6= −(m + c), then, k + m + c ∈ {−(n − 1), . . . , (n − 1)} except 0. Hence, the inner summation
is 0. Thus, we have,
Problem 2. Design a variant New Partition of the Partition(A, p, r) procedure that runs in time O(r −
p + 1) and divides the input array A[p . . . r] into three subarrays A[p, . . . , q − 1], A[q, . . . , s − 1] and
A[s, . . . , r]. Let key denote the value A[r] in the original array A. After New Partition(A, p, r), each
element of A[p, . . . , q − 1] is strictly less than key, the elements A[q, . . . , s − 1] are identical in value to
each other and to key, and each element of A[s, . . . , r] is strictly greater than key. New Partition returns
the pair (q, s), where, p ≤ q < s ≤ r.
a. Describe clearly the invariant that your loop satisfies (use a figure if it helps), and show how you will
process the next element of the array so that the loop invariant is maintained. (10)
b. Based on the loop invariant, write pseudo-code for New Partition(A, p, r). (10)
Solution Outline. Let j be the running counter from p to r − 1. Invariant: Let A[p . . . i] be each < A[r],
A[i + 1, . . . , k] be each equal to A[r] and A[k + 1, . . . , j − 1] be each > A[r]. The region A[j . . . r − 1] is
unrestricted.
Initially, to maintain the invariant, let i = p − 1, k = p − 1. Loop counter j runs from j = p . . . r − 1 as a
for loop.
1. A[j] > key. We do nothing, and j will be incremented in the for loop. Invariant is preserved.
3. A[j] < key. Now A[j] should be copied to position A[i + 1]. To make room at position i + 1,
A[i + 1] should be copied to position A[k + 1], A[k + 1] should be copied to A[j], all simultaneously.
Increment i and k. We can do this with the sequence
key = A[j]; A[j] = A[k + 1]; A[k + 1] = A[i + 1]; A[i + 1] = key; i = i + 1, k = k + 1;
Equivalently, we can exchange A[j] with A[k+1], then exchange A[k+1] with A[i+1]; now increment
i and k.
2
New Partition(A, p, r)
1. pivot = A[r]
2. i = p − 1; k = p − 1
3. for j = p to r − 1
4. if A[j] == pivot {
5. exchange A[k + 1] with A[j]; k = k + 1 }
6. elseif A[j] < pivot {
7. exchange A[j] with A[k + 1]
8. exchange A[k + 1] with A[i + 1]
9. k = k + 1; i = i + 1 }
10. }
11. exchange A[r] with A[k + 1] ; k = k + 1
12. return (i + 1, k + 1)
Time complexity is obviously Θ(r − p + 1). For each index j = p . . . r, Θ(1) number of comparisons and
operations are done. The quicksort pseudo code is as follows. Top-level call is Quicksort(A, 1, n).
Problem 3. Given an array A[1, . . . , n] of integer numbers, give an algorithm to sort A in time O(n+M )
where,
M = (max A[i]) − (min A[i]) .
i i
Give an outline of the algorithm and then argue its time complexity. (18 + 7)
Solution outline.
1. Make a single pass over A[1 . . . n] and find k = minni=1 A[i] and K = maxni=1 A[i]. This takes O(n)
time
2. Create a new array C[k, . . . , K], each array has two fields C[l].f (frequency) and C[l].s (cumulative
frequency). WePwant C[l].f to be the number of occurrences of l in A[1 . . . n]. C[l].s is cumulative
frequency = x lr=k C[r].f . Takes time O(M + 1).
4. Count the number of times l occurs in A[1 . . . n], for k ≤ l ≤ K, as follows. This is frequency count.
This takes time O(n) time.
for i = 1 to n {
C[A[i]].f = C[A[i]].f + 1 }
3
Pl
5. Make a pass over the array C[k . . . K] to get cumulative frequencies C[l].s = r=k C[r].f . Takes
time O(M + 1).
sum = 0
for l = k to K {
C[l].s = sum + C[l].f
sum = sum + C[l].s }
6. Make an empty copy of A[1 . . . n] in B[1 . . . n]. Time O(n).
7. Make a backwards pass over A, that is, for i = n down to 1. Index of A[i] is C[A[i]].cumul, and
decrement C[A[i]].cumul by 1. Time: O(n)
for i = n downto 1 {
posn = C[A[i]].s
B[posn] = A[i]
}
C[A[i]].s = C[A[i]].s − 1 // reduce cumulative frequency of A[i] by 1
Total time is O(n + M ).
Problem 4. You are given k sorted arrays with a total number of n elements across all the arrays. We
wish to merge them into a single sorted array of kn elements. Describe an O(n log k)-time algorithm for
this problem. (25 points)
Solution outline. Keep a min-heap or min-priority queue H. Each entry is a pair (v, i), where, v is the
key value and i is array number between 1 and k from which this element has been picked. The ith array
is A[i, 1] . . . A[i, N [i] + 1]. Assume N [i] is the number of items in the ith array and A[N [i] + 1] = ∞.
1. Initialize Heap.
1. for i = 1 to k
2. Insert(H, (A[i, 1], i))
3. create empty array B[1 . . . n]
4. for i = 1 to k
5. N [i] = 2 // current index of next smallest element in ith array
The time taken is O(k log k) for the for loop in lines 1-2.
2. Extract the smallest element from the heap. Let (v, i) = Extract-Min(H). Place v at the current
end j of union array B. Insert next item from array i into Heap H.
1. for j = 1 to n {
2. (v, i) = Extract-Min(H)
3. B[j] = v
4. Insert(H, A[i, N [i]])
5. N [i] = N [i] + 1
6. }
The heap has k elements, the current min from each of the k arrays. The operation Extract-Min
takes time O(log k). Insert also takes time O(log k). Total time of the loop is O(n log k).