HW1 Sol
HW1 Sol
HW1 Sol
Homework 1
Instructor: Shi Li Deadline: 2/24/2021
Problems 1 2 3 Total
Max. Score 10 16 14 40
Your Score
Problem 1. For each pair of functions f and g in the following table, indicate whether
f = O(g), f = Ω(g) and f = Θ(g) respectively. Justify your answer for the question
“whether d10n1.9 e = O(n2 )?”, using the definition of the O-notation.
f (n) g(n) O Ω Θ
log10 n 5 log2 (n3 ) yes yes yes
d10n1.9 e n2 yes no no
n2 − 100n 10n log n no yes no
Algorithm (2a)
1: for i ← 1 to n − 1 do
2: for j ← i + 1 to n do
3: if A[i] + A[j] = 0 then return yes
4: return no
• Algorithm (2a) simply enumerates all pairs (i, j) with 1 ≤ i < j ≤ n and checks if
A[i] + A[j] = 0 for some pair. The algorithm runs in O(n2 ) time.
1
Algorithm (2b)
1: for i ← 1 to n − 1 do
2: ` ← i + 1, r ← n
3: while ` ≤ r do
4: m ← b(` + r)/2c
5: if A[m] = −A[i] then return yes
6: if A[m] < −A[i] then ` ← m + 1 else r ← m − 1
7: return no
Algorithm (2c)
1: i ← 1, j ← n
2: while i < j do
3: if A[i] + A[j] = 0 then return yes
4: if A[i] + A[j] < 0 then i ← i + 1 else j ← j − 1
5: return no
• Algorithm (2b) first enumerates i from 1 to n − 1, and then uses a binary search to
check if there is an index j in [i + 1, n] such that A[j] = −A[i]. In the binary search
procedure, it maintains two pointers ` and r so that if such a j exists, then it must
be in [`, r]. In each iteration, it takes the middle element A[m] in the sub-array
A[`..r]. If A[m] = −A[i] then such j exists; if A[m] < −A[i], j must be in [m + 1, r];
if A[m] > −A[i], j must be in [`, m − 1].
For each iteration i for the outer loop, the running time of the algorithm is O(log(n−
i)) = O(log n). So overall the running time is O(n log n).
• Algorithm(2c) maintains two pointers i and j. We are guaranteed at any time that
if some pair i0 , j 0 satisfies 1 ≤ i0 < j 0 ≤ n and A[i0 ] + A[j 0 ] = 0, then it must be the
case that i ≤ i0 < j 0 ≤ j. This is clearly true initially since i = 1 and j = n. If
A[i] + A[j] = 0, then such a pair exists. If A[i] + A[j] < 0, then A[i] + A[j 0 ] < 0
for every j 0 ∈ [i + 1, j]. So, the element A[i] is useless and we can increase i by 1.
Similarly, if A[i] + A[j] > 0 and the element A[j] is useless and we can decrease j
by 1. So, after each iteration, the property is still guaranteed.
In each iteration, j −i will be decreased by exactly 1 and so the number of iterations
that the algorithm runs is at most n. Each iteration takes O(1) time and the running
time of the algorithm is O(n).
Problem 3. In the class, you learned how to check if a graph is bipartite or not. In this
problem, we assume the given graph G = (V, E) is not bipartite. Design an O(n+m)-time
algorithm that outputs an odd cycle in G.
In Algorithms 1 and 2, we use DFS to color all vertices in the graph G. color[v] will
store the color of v and parent[v] will give store the parent of v in the DFS tree. (u∗ , v ∗ )
gives a bad edge; namely an edge with both vertices having the same color. It is known
that every edge that is not in the DFS tree must connect a vertex to its ancestor in the
DFS tree. Therefore, v ∗ will be an ancestor of u∗ . The cycle will be formed by the edge
2
(u∗ , v ∗ ) and the path from v ∗ to u∗ in the DFS tree. It is printed in Step 5-9 of the main
algorithm.
The running time for the iteration of DFS for v is O(dv ), where dv is the degree of v.
So overall the running time for all recursions of DFS is O(m + n).