hw02 Solution PDF
hw02 Solution PDF
CSCI-GA.1170-001/Summer 2016
Solution to Homework 2
Problem 1. (2 points) For the following recurrences, obtain a solution using the master method
(or explain why not applicable), then give a substitution proof for the upper bound:
(a) T (n) = 4T ( 3n ) + n. (CLRS 4.3-7)
(b) T (n) = 4T ( 2n ) + n2 . (CLRS 4.3-8)
(c) T (n) = 4T ( 2n ) + n2 lg n. (CLRS 4.5-4)
Solution:
(a) The recurrence T (n) = 4T ( 3n ) + n is of the form T (n) = aT ( nb ) + f (n), and n = O(nlog3 4 ),
so we can apply case 1 of the master method to obtain T (n) = (nlog3 4 ).
Let us verify the upper bound T (n) = O(nlog3 4 ) by substitution. (By convention, we assume
T (0) = (1) or T (1) = (1), as appropriate, and omit the base cases in this and other
inductive proofs.)
With inductive hypothesis:
T (k) cklog3 4 for all 0 < k < n,
Let us perform the inductive step by showing:
T (n) cnlog3 4 .
(1.1)
(1.2)
log 4
3
n
n
c2
+ n,
T (n) 4 c1
3
3
4
T (n) c1 nlog3 4 c2 n + n.
3
Showing (1.2) is thus equivalent to showing:
4
c1 nlog3 4 c2 n + n c1 nlog3 4 c2 n,
3
4
c2 n + n c2 n,
3
4
c2 + 1 c2 ,
3
c2 3.
Which does not contradict any of our assumptions and thus completes the inductive step
and the proof.
(b) The recurrence T (n) = 4T ( 2n ) + n2 is of the form T (n) = aT ( nb ) + f (n), and n2 = (n2 ), so
we can apply case 2 of the master method to obtain T (n) = (n2 lg n).
Let us verify the upper bound T (n) = O(n2 lg n) by substitution.
With inductive hypothesis:
T (k) ck2 lg k for all 0 < k < n.
Let us perform the inductive step by showing:
T (n) cn2 lg n.
By definition of T (n) and then by inductive hypothesis:
n
+ n2 ,
T (n) = 4T
2
2
n
n
T (n) 4 c
lg
+ n2 ,
2
2
n
2
2
T (n) cn lg + n ,
2
2
T (n) cn lg n cn2 + n2 .
(1.3)
c
if n = 0,
T (n) =
aT (n 1) + k if n > 0.
Solution: Computing the first few values:
T (0) = c
T (1) = aT (0) + k = ac + k
T (2) = aT (1) + k = a(ac + k) + k = a2 c + ak + k
T (3) = aT (2) + k = a(a2 c + ak + k) + k = a3 c + a2 k + ak + k
Seems to suggest:
T (n) = a c +
n
n1
X
i=0
a i k.
(1.4)
For a = 1 we have:
T (n) = c +
n1
X
k = c + nk.
(1.5)
i=0
1 an
.
1a
1 an
.
1a
And performing the inductive step to show that (1.6) holds for n + 1:
T (n) = a n c + k
T (n + 1) = a
n+1
1 a n+1
.
c+k
1a
1 an
n
+ k.
=a a c+k
1a
Simplifying:
1 an
+k
1a
a(1 a n ) + (1 a)
= a n+1 c + k
1a
n+1
1
a
= a n+1 c + k
.
1a
T (n + 1) = a n+1 c + ka
(1.6)
With the base case and inductive step in place for both (1.5) and (1.6), we conclude that (1.4)
holds for all natural numbers n and all values of c, a, and k.
Problem 3. (2 points) Give pseudocode for iterative binary search. Prove correctness of your
algorithm using a loop invariant, state the worst-case running time.
Solution:
Iterative binary search in Python:
1
2
3
4
5
6
7
8
9
10
11
12
2. ke y < a[mid]. The adjusted range [lo, mid) is strictly smaller than the original
range [lo, hi):
mid lo < hi lo,
mid < hi,
hi lo
lo +
< hi,
2
hi lo
< hi lo.
2
hi lo
hi lo
=
,
2
2
hi lo
< hi lo,
2
hi lo > 0.
Odd hi lo gives:
hi lo
hi lo 1
=
,
2
2
hi lo 1
< hi lo,
2
hi lo > 1.
The worst-case running time can be observed when ke y is not present in a and the
algorithm terminates due to hi lo 0. Each iteration of the loop reduces the range
from [lo, hi) to either [lo, mid) or [mid +1, hi) and thus reduces the number of elements
in the range to either mid lo or hi mid 1. By definition of mid:
hi lo
hi lo
lo =
,
mid lo = lo +
2
2
hi lo
hi mid 1 = hi lo
1.
2
Considering even hi lo:
mid lo =
hi lo
,
2
hi mid 1 = hi lo
hi lo
hi lo
1=
1.
2
2
Thus, hi lo, initially equal to len(a), is reduced roughly in half each iteration, leading
to the worst-case running time of (lg n) with n = len(a).
Problem 4. (2 points) Give pseudocode for recursive binary search. Formulate and solve a
recurrence describing the worst-case running time.
Solution:
Recursive binary search in Python:
1
2
3
4
5
6
7
8
9
10
Problem 5. (3 points) Let A = (a1 , a2 , ..., an ) be a sequence of n distinct numbers. A pair (i, j)
is called an inversion of A if i < j and ai > a j . Give pseudocode for a modification of merge
sort to count the number of inversions of the sequence. Formulate and solve a recurrence
describing the worst-case running time.
Solution:
Considering an execution of merge(left, right) with i and j keeping track of the current element in left and right respectively, we observe that taking element right[j]
before exhausting all elements in left, indicates that right[j] forms inversions with all
len(left) - i yet unprocessed elements in left. We then extend a typical implementation of mergesort with code to:
1. Count the number of inversions right[j] forms with elements in left (line 25).
2. Return the total number of inversions detected by this invocation of merge (line 30).
3. Return the total number of inversions detected in left subarray, right subarray, and
inversions crossing the boundary between two subarrays (lines 6-8 and 10).
Resulting in the following Python code:
def mergesort (a ):
if len (a) < 2:
return a , 0
mid = len (a) / 2
left , inv_left = mergesort (a [: mid ])
right , inv_right = mergesort (a[ mid :])
merged , inv_split = merge ( left , right )
return merged , inv_left + inv_right + inv_split
def merge ( left , right ):
merged = []
i = 0
j = 0
inv = 0
while i < len ( left ) and j < len ( right ):
if left [i] <= right [j ]:
merged . append ( left [i ])
i += 1
else :
merged . append ( right [j ])
j += 1
inv += len ( left ) - i
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30