University of Toronto ECE-345: Algorithms and

University of Toronto
ECE-345: Algorithms and Data Structures
Solutions to Midterm Examination (Winter 2016)
3
+2n
≤ cn2 . Choose c = 0.5. Then, we
1. (a) We need to find constants c and n0 such that if n ≥ n0 , then n2n+1
need:
n3 + 2n ≤ 0.5n2 (2n + 1) = n3 + 0.5n2
Therefore, we need n ≥ 4 = n0 .
(b) The inner loop runs for log3 (x) times for every x = 1, 2, 4, . . . , n. Accordingly, the running time is:
log3 (1) + log3 (2) + log3 (22 ) + . . . + log3 (2log2 n ) = log3 (2) + 2 log3 (2) + . . . + log2 (n) log3 (2)
= log3 (2) (1 + 2 + . . . log2 (n))
= log3 (2)
log2 (n)(log2 (n) + 1)
= Θ log2 (n)
2
(c) Induction Base: for n = 1, both sides
Pn of the equality are exactly 2.
Induction Hypothesis: Assume i=1 i · 2i = (n − 1) · 2n+1 + 2.
Induction Step: We have:
n+1
X
i · 2i =
n
X
i · 2i + (n + 1) · 2n+1
i=1
i=1
= (n − 1) · 2n+1 + 2 + (n + 1) · 2n+1
= (2n) · 2n+1 + 2 = n · 2n+2 + 2
Therefore, the identity is true by induction.
(d) The Master Theorem applies for both:
i. Case 3: a = 6, b = 3, and logb (a) = log3 (6) < log3 (9) = 2. Hence, we have:
n2 lg n = Ω nlog3 (6)+
when 0 < < 2 − log3 (6). Still need to check the regularity condition. We have:
n2 n
2
n
2
2
lg = n2 lg ≤ n2 lg n = f (n)
b
9
3
3
3
3
3
Therefore, by case 3 of Master Theorem, T (n) = Θ n2 lg n .
ii. Case 1: a = 10, b = 3, and logb (a) = log3 (10). Hence, we have:
17n1.2 = O nlog3 (10)−
af
n
=6
where 0 < < log3 (10) − 1.2. Therefore, by case 1 of Master Theorem, T (n) = Θ nlog3 (10) .
1
(e) The resulting heap and BST are as follows.
18
94
8
12
97
11
4
6
1
7
24
5
5
3
17
2
Figure 2: New BST
Figure 1: New Heap
(f) We answer the question “How many ways are there to select 2 objects from a set of size 2n?” This is
the left-hand side by definition
of nk . For the right-hand side, we divide the objects into two groups
of size n. Now there are n2 ways to select both objects from the first group. Similarly, there are n2
ways to select both objects from the second group. The only other case is that we select one object
2
from each of the groups, in which case there are n choices for each object,
total. Since these cases
or n
n
2
are disjoint, the total number of ways to select 2 objects from 2n is 2 2 + n .
2. We can use a divide-and-conquer algorithm very similar to randomized quicksort. The algorithm initially
performs a partition operation as follows: pick a random cap C[i]. Using this cap, rearrange the array
of bottles into three groups of elements: first the bottles smaller than C[i], then the bottle that matches
C[i], and finally the bottles larger than C[i]. Next, using the bottle that matches C[i] we perform a similar
partition of the array of caps. This pair of partitioning operations can be implemented in Θ(n) time, and it
leaves the caps and bottles partitioned so that the “pivot” cap and bottle are aligned with each other and all
other caps and bottles are on the correct side of these pivots. Our algorithm then continues by recursively
applying itself to the subarrays on the left and right of the pivot position to match these remaining caps
and bottles. By induction on n these recursive calls will properly match the remaining bottles. To analyse
the running time of our algorithm, we can use the same analysis as that of randomized quicksort. We are
performing a partition operation in Θ(n) time that splits our problem into two subproblems whose sizes are
randomly distributed exactly as would be the subproblems resulting from a partition in randomized quicksort.
Therefore, applying the analysis from quicksort, the expected running time of our algorithm is Θ(n logn).
3. (a) For each j = 1, . . . , n we will compute (solve) the following sub-problem:
M (j) : the maximum sum contiguous subsequence that ends with element sj .
Overall we want to compute max1≤j≤n M [j].
(b) Base Case: M [1] = s1 .
In general, you either extend an optimal subsequence ending at position j − 1 by including element sj ,
or you start a new subsequence containing only sj .
M [j] = max{M [j − 1] + sj , sj }
(c) Just build M [1] to M [n] in this order using the recurrence in part (b), and finally calculate max1≤j≤n M [j].
To remember which subsequence corresponds to the maximum, there are many equivalent ways to do
it. We will keep an array of booleans B[1 . . . n] (you can use backpointers too). At step j in your
algorithm’s for-loop, set B[j] = 1 if you extended the window from j − 1, and B[j] = 0 if you started
a new window. Say the optimal subsequence computed using max1≤j≤n M [j] is for the subsequence
ending at index k. To know where this subsequence starts, go back from k until you get the first index
l such that B[l] = 0. The maximum sum window will be sl+1 . . . sk . Runtime is O(n).
2