You are on page 1of 3

CSE 431/531: Algorithm Analysis and Design Spring 2021

Homework 1
Instructor: Shi Li Deadline: 2/24/2021

Your Name: Your Student ID:

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

Let n0 = 1 and c = 11. For every n ≥ n0 = 1, we have

10n1.9 ≤ 10n1.9 + 1 ≤ 10n2 + n2 = 11n2 = cn2 .


 

Problem 2. We are given an sorted array A of n integers (which may be negative, 0,


or positive). We need to check if there are two integers in the array with sum 0. For each
of the following three algorithms (2a), (2b) and (2c), briefly explain its correctness and
give its running time. The running times you give should be tight.

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).

Algorithm 1 The main algorithm.


1: for every v ∈ V do color[v] ← −1
. −1 means not colored. Algorithm 2 DFS(v)
2: for every v ∈ V do 1: for every u such that (v, u) ∈ E do
3: if color[v] = −1 then 2: if color[u] = −1 then
4: color[v] ← 0 and call DFS(v) 3: parent[u] ← v
∗ 4: color[u] ← 1 − color[v]
5: v ← v
5: DFS(u)
6: while v 6= u∗ do
6: else if color[u] = color[v] then
7: print v
7: (u∗ , v ∗ ) ← (u, v)
8: v ← parent[v]
9: print v

You might also like