You are on page 1of 16

Anyone with the link can edit now. Kk thx bai GLHF.

X
Advanced Algorithms & Data Structures
November 8, 2018
The University of Queensland COMP4500/COMP7500
Dr Larissa Meinicke 2018, Semester 2

[Exam Paper]

Question 1. Recurrence Relations [10 marks] (2 parts)

a) [5 marks] T (n)=8 T (n/2)+ n(n+1)


b) [5 marks] T (n)=3 T (n/4 )+ nlo g2 n

Solution:

a) T (n)=8 T (n/2)+ n(n+1)

WTP: n(n + 1) = O(n2 ) (+1)


Need c, n0 s.t. For all n≥n0 , 0≤n2❑+ n≤c n2 , where c , n0 >0
0≤n2 if n>0
n2 +n≤c n2 if n≥1∧c≥2
So n0 =1 ,c =2suffices n(n + 1) = O(n2 )

Applying master’s theorem:


T (n)=8 T (n/2)+ O(n2 )
a = 8; b = 2
n2 /nlo g 8 =n2 /n3=n2 n−3=n−1=O(n−e ), where e = 1 > 0.
2

So by the master theorem’s case 1, T(n) = Θ(nlo g 8 ) = Θ(n3 ) 2

b) T(n) = T (n)=3 T (n/4 )+ nlo g2 n, a = 3, b = 4


¿ nlo g 2 n /nlo g 3=nlo g2 n/n(lo g 3 /lo g 4 )=nlo g2 n/n(about 1.5/2)
4 2 2

¿ nlo g 2 n /n(¿0.75 )=n(0<e) lo g2 n belongs to omega n^(1-0.75) where e(1-0.75) > 0

So by the master theorem’s case 3, T(n) = Θ(nlo g 2 n )


af(n/b) <= cf(n)
3(n/4log2(n/4)) = 3n((log2n)-2)/4
= 3/4nlog2n -(3/2) n <= cnlog2n
Where c = ¾ <1
Anyone with the link can edit now. Kk thx bai GLHF.
Anyone with the link can edit now. Kk thx bai GLHF.
Question 2. Recurrences - Substitution Method [10 marks]

WTP: T(n) = O(n lg n)


Need c, n0 > 0 s.t. For all n >= n0 , 0 <= T(n) <= cn lgn//
I think we need to find a T(n) <= cn lgn+bn+d, such that T(n) = 1 <= cn lgn+bn+d, for all n=1,2,3..,7 to
satisfy the Base Case. n0 = 1 below does not satisfy the base case.
Base case:
Try n0 = 1
T(1) = 1 > c1 lg1

Try n0 = 2
No n >= 2 directly dependent on T(1) and:
T(2) = 1 <= c2 lg2

if c >= 1
=>n0 = 2

Inductive step:

assume inequality holds for T(floor(n/4)) and for T(floor(3n/4))

T(n) <= cn lgn

<= [(cn)/4 lg(n/4)] + [(3cn/4) lg(3n/4)] + n

<= cn/4(lgn - lg4) + 3cn/4(lg3n - lg4) + n

<= cn lgn/4 - 2cn/4 + 3cnlg3n/4 - 6cn/4 + n

<= cn lgn/4 - 8cn/4 + n + 3cn/4(lg3 + lgn)

<= cn lgn/4 - 2cn + n + 3cn lg3/4 + 3cn lgn/4

<= cn lgn - (2cn - n - 3cn lg3/4)

<= cn lgn

if 2cn - n - 3cn lg3/4 >= 0


Anyone with the link can edit now. Kk thx bai GLHF.

2cn - n - 3cn lg3/4 >= 0


Let n = 2, c = 4
2 . 4 . 2 - 2 - (3 . 4 . 2 lg3/4) >= 0
14 - 6 lg3 >= 0

lg3 < 2
14 - 6 . 2 >= 0
14 - 12 = 2 >= 0

So n0 = 2 and c = 4 will suffice. (c = 2)


Anyone with the link can edit now. Kk thx bai GLHF.
Question 3. Amortised Analysis [20 marks] (3 parts)

I got ceil( (m - n)/2 )?? Or floor( (m - n - 1) / 2) -1

Not sold on these answers? My thinking is this:


Let A have size 8 (could be any power of two), so n = 8
Start with empty array so size = 0

Perform first insert operation with x = 1:


A = [1]
Size = 1

Fill the rest of the array with 2, 3, 4, 5, 6, 7, 8


A = [1, 2, 3, 4, 5, 6, 7, 8]
Since size is incremented after an element is added, we fully fill the array and finish with size = 8

The next call to insert results in half the array being deleted since size == n.
Assume for now that rearrangement does nothing.
A = [1, 2, 3, 4] & size = 4
(Technically A is still [1, 2, 3, 4, 5, 6, 7, 8] since we don’t actually delete the elements but rather reset the
cursor of the list to override from n/2 but for demonstration I will leave it as half the array).
Therefore at the 9th operation m, we have our first call to REARRANGE (the second line of the function)
Since we now have half the array, we insert the new element.
A = [1, 2, 3, 4, 9] & size = 5
Note that this still occurs at m = 9.

You should see now that 10, 11, 12 will all be inserted normally without rearranging to reach:
Anyone with the link can edit now. Kk thx bai GLHF.
A = [1, 2, 3, 4, 9, 10, 11, 12] & size = 8
The next insert again calls rearrange so at m = 13 we have called rearrange twice.

Extending this out:

m 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

#Rearrange 0 0 0 0 0 0 0 0 1 1 1 1 2 2 2 2 3
v
Which gives the function:

0 for m <= 8
2( m−1)
floor ( −1) for m > 8 (+3)
n

I have another solution: t = ceiling(2(m-n)/n) for m > = n. I think it returns the same value
t when m is an integer.(+3)Should be m>n. Looking at the above example it is trivial to see
that when m=n there are 0.

Please let me know if I read the question wrong.

I also have another solution: floor((2m-n)/n-1) for m>=n.

Helppppp 2020

Not sure if right:


Time to insert is: floor 2 ( ( m−1)
n
−1 )* n
Making it roughly O(n^2)

O(n^2) / n operations makes it O(n) using an aggregate method. For example m = 5,000,000 and n = 100.
The value converges to O(1) < m < n, O(n^2) when m <= 4n + 1 and O(n) when m > 4n + 1

Another solution:
(m−1)
⌊2 −1 ⌋
m n
for m > n
∑ ci ≤ m+ ∑ Θ( n)
i=1 i =1
m
≤ m+ 2 Θ(n)
n
≤3m
¿ Θ(m) (+1) (how did you get rid of n? I think O(m) is not tight enough) -> as only if m is greater then n,
Anyone with the link can edit now. Kk thx bai GLHF.
then rearrange method will be called, so if m = 9, and n = 8, whole cost is 17, but when m = 10, whole
cost is 19, when 2m/n * n = 2m

I got:
The costs of line 1, 4, 5 are 3
3m + floor(2(m-1)/n - 1) * Θ(n)
<= 3m + [2(m-1)/n - 1] * cn
= 3m + c*(2m - 2 - n)
= (3+2c)m - cn -2c
= O(m - n)
Anyone can tell me if I am wrong? I got this too (and it makes sense, higher n means fewer rearranges).
Just need to make sure m >= n. Not sure how to work it into c though. +1

If the answer to (b) is Θ(m),


Θ(m)
=Θ(1) (+1)
m
O(m-n)/m = O(1)
I think O(1) looks legit, i’m thinking from the accounting method perspective; if an array has size=n, then
all n elements will be rearranged everytime we want to insert an element into a full array (and it is
possible for an element x to be in the array since day 1 and be rearranged for all m insertions bc it
coincidentally always ended up in the first half of the array). This means for each insert, they should be
charged extra to cover (1) itself, and (2 | n) for the existing half of the array to be rearranged when the
array is full again. So each insert should have an amortized cost of 2 (from the nth insert onwards i guess,
the first 4 | n/2 can have a cost of 1 LOL idk if any of this makes sense it’s almost 3am) which is therefore
O(1).
Anyone with the link can edit now. Kk thx bai GLHF.

Question 4. Graphs [20 marks] (1 part)

It would be smart to draw the graph out.

Iteration 1:

e.d=∞, e.𝜋=NIL; d.d=∞, d.𝜋=NIL; c.d=∞, c.𝜋=NIL; b.d=1, b.𝜋=a; a.d=0, a.𝜋=NIL
Iteration 2:
b.d=1, b.𝜋=a, e.d=∞, e.𝜋=NIL; d.d=∞, d.𝜋=NIL; c.d=3, c.𝜋=b; a.d=0, a.𝜋=NIL
Iteration 3:
b.d=1, b.𝜋=a, e.d=4, e.𝜋=c; d.d=4, d.𝜋=c; c.d=3, c.𝜋=b; a.d=0, a.𝜋=NIL
Iteration 4:
b.d=0, b.𝜋=d, e.d=4, e.𝜋=c; d.d=4, d.𝜋=c; c.d=2, c.𝜋=b; a.d=0, a.𝜋=NIL
Iteration 5: to be pedantic: Bellman-Ford doesn’t set distances during the final iteration. It just
returns False as soon as an edge could be relaxed. So the states of the vertices after iteration 4 will
be the same as after iteration 5.
b.d=0, b.𝜋=d, e.d=3, e.𝜋=c; d.d=3, d.𝜋=c; c.d=2, c.𝜋=b; a.d=0, a.𝜋=NIL
THis shouldn't be updated in iteration 5 then??
-> Yup, only need to relax |V| - 1 times
Returns FALSE because the edges can be relaxed at iteration v

Vertices: b, c, d - what about e? ( a => b => c => d => b => c => d )


It’s a negative cycle at the second b loop.

Maybe b c d but Wikipedia says a path should only contain distinct/repeated points.
My take- The lecture notes differentiate between simple and normal paths, so I would say b,c,d,e
assuming the path is not normal. (+1)

So which one is correct???


Weight cycle can’t include e since there is no path from e to anything, so cannot be a cycle - cheers,
Ahmad (+2) +3 +9 +10
Anyone with the link can edit now. Kk thx bai GLHF.

7 S = {}
8 for i = 1 to |G.V| - 1
9 for each edge (u, v) in G.E
10 if v.d > u.d + w(u, v)
11 S.add(v) // Because set contains unique vertices, add() will only add if v not in S

Relax(u,v)
12 return S (+1)
Updated w.r.t responses pointing out errors below: you also need to relax on each step here ^, like
so.
This is because an optimal path without a negative weight cycle will be no more than |V| - 1 edges
long (i.e. visits every vertex once, that’s why the first loop is restricted to that). The idea is we need to keep
relaxing after this, because if anything can relax further, it’ll be because it has a neg-weight cycle. Worst
case we have an awkward edge order and we can only relax one edge per iteration, so we need the whole
loop.
For above code
At iteration 3, where b.d = 1, d.d = 4, weight is -4, which 1 > 0 , so b is added, then next (ignore
de,cd,cd) b to c c.d = 3, b.d = 0, weight is 2, so 3 > 2, c is added, next iteration 4, where c to d is updating,
d.d = 4, c.d = 2, weight is 1, 4 > 2+1, this is correct when negative cycle is happens, it will return all the
negative cycle vertice, the return should change to return g.v
(but it says: the return value is the empty set if the graph contains no negative weight cycles,
should this be: (isnt code is saying that if negative cycle is happen clean all and return it????)
7 S = {}
8 for i = 1 to |G.V| - 1
9 for each edge (u, v) in G.E
10 if v.d > u.d + w(u, v)
11 S.removeAll()
12
return S
13 return S
)
Anyone with the link can edit now. Kk thx bai GLHF.
Other answer:
(Outer loop unnecessary, and source vertex should also be added to the set) +1
-Outer loop is not unnecessary. This answer does not include vertex B.
7 S={}
8 for each edge (u, v) in G.E
9 if v.d > u.d + w(u, v)
10 S.add(u)
11 S.add(v)
12 return S
I am afraid these answers above does not include vertex b in the solution set +1

Need to update the weights.

Need to keep relaxing and adding vertices to the set while there are new edges to relax.

def solve(G, w, s):

# replace lines 8 through 10 with the code below


cycle = set()
loop = True
while loop:
loop = False
for (u, v) in G.E:
if v.d > u.d + w(u,v):

v.d = u.d + w(u,v)


if v not in cycle:
cycle.add(v)
loop = True

return cycle
Anyone with the link can edit now. Kk thx bai GLHF.

Question 5. Dynamic Programming [25 marks] (2 parts)

a.
Piazza’s solution +1

Base cases for the above solution: i>j => M(i,j) = 0 (it doesn't need the i=j case)
B.
For i from n to 1
For j from 1 to i (i always > j)
Anyone with the link can edit now. Kk thx bai GLHF.
Build base case first if i>j

For i from n to 1 (construct subproblems from the middle to the left and right)
For j from i to n (i always <= j)
Build table for general cases

How I would answer this question:


M(i,j)=max{
v[i]+min(M(i+2,j),M(i+1,j−1)
i.e. you pick player
i
then your opponent makes a strategic choice between players
i+1
and
j
v[j]+min(M(i,j−2),M(i+1,j−1)
i.e. you pick player
j
then your opponent makes a strategic choice between players
i
and
j−1
}

See Problem 8 here for similar problem solution:


http://courses.csail.mit.edu/6.006/oldquizzes/solutions/final-f2009-sol.pdf#page=12

(a) You want to

M(i, j) = // Need init step


For 1 < i < n-1
For i % 2 <= j <= n

v[i] , if i = j
0 , if i > j
max(v[i] + M(i + 1, j), v[j] + M(i, j - 1)) , if i < j <= n

MaxValue(v):
// Build array
M[v.length][v.length] // First choice
N[v.length][v.length] // Second choice
For i < n:
M[i][i] = v[i]
N[i][i] = 0
Anyone with the link can edit now. Kk thx bai GLHF.
For l <= n:
For i <= n - l + 1:
j = i + l - 1
If N[i + 1][j] + v[i] < N[i][j - 1] + v[j]:
M[i][j] = N[i][j - 1] + v[j]
N[i][j] = M[i][j - 1]
Else:
M[i][j] = N[i + 1][j] + v[i]
N[i][j] = M[i + 1][j]
Return N(1, n)

I disagree with the above. The pdf link there also doesn’t quite match, because in this case, BOTH
coaches can see all players’ scores.

My reasoning: When we get M(i, j), it’s our turn. But when we take one off, and get M(i + 1, j) or M(i, j
- 1), it’s then the opponent’s turn.
In this case, we don’t want to maximise the next level of recurrence, we want to minimise it. My
solution:

M(i, j) = (Sum_{n = i}^j v[n]) - min(M(i + 1, j), M(i, j - 1))

Here, we sum up the total points available, and then make the choice (via the min func) that
minimises the score the opponent can get on the next step (and onwards). Consequently, we
maximise the score we can get on the next step (and onwards).

To go with my suggested answer for a) above:

Concept: Walk over the values array, with a larger ‘window size’ (size of the sub-array) each time. i.e.,
start with window size 0, so M(k, k), which is the base case, and work out M(1, 1), M(2, 2), …
Then, increase window size to 1, and do M(1, 2), M(2, 3), …, using the window size 0 results (base cases).
Then, window size 2, doing M(1, 3), M(2, 4), …, using window size 1 results. And so on.
Repeat until you have window size (n - 1), which is just M(1, n).

Pseudocode:

M := 2D array of size n*n

For wSize = 0 to (n - 1): // Window size


For start = 1 to (n - wSize): // Array start position for the window
If wSize == 0: // Base case
M[start, start] = v[start];
Else:
end := start + wSize; // Array end position for the window
M[start, end] = (Sum_{i = start}^{end} v[i]) - min(M[start + 1, end], M[start, end - 1]);

Return M[1, n];

Had a comment saying that my recurrence here is different to the above, I suspect this was because of a
bad choice of variable names, I’ve updated it to hopefully make more sense.
Anyone with the link can edit now. Kk thx bai GLHF.

My answer:

Question 6. Reductions [10 marks] (2 parts)

(a) [5 marks] Prove that the weighted-clique problem is NP-hard.


Do u agree with below?

Reduce NPC problem to our new Problem eg. use clique to solve weighted-clique

Weighted Clique(G, w, c):


for i = 1 to |G.V

C = Clique(G, i) // Check if we have a cliqu

weight =
Anyone with the link can edit now. Kk thx bai GLHF.
for j = 1 to |C.V
for z = j + 1 to |C.V|

weight += w[C.E[C.V[ z ], C.V[ j ]

if weight >=

return tru

Alternative answer:

If we set w=1 for all edges, and c=k, the weight-clique problem is reduced to the clique problem,
which we know is NP-hard.
∴ The weighted-clique problem is also NP-hard.

Almost: we’re reducing the clique problem/CP to the weighted clique problem/WCP, rather than
the reverse. (So that any problem can be transformed into CP => transformed into WCP => any
problem can be transformed into WCP => WCP is NP-hard).

Then, set w=1 for all edges as you say, but c = k(k-1)/2.
Bit of graph theory here: if all n vertices in a graph are connected to each other, it has at least
n(n-1)/2 edges.

SOLVE-CLIQUE(G,k)
For e in G.edges
e.weight = 1
Return SOLVE-WEIGHTED-CLIQUE(G, k(k-1)/2) (+1)

(b) [5 marks] Show that the weighted-clique problem is NP-complete and clearly state any
assumptions that you make.

Do u agree with below? +2

Above we have proven the weighted clique is NP-Hard.


We must now show it is within NP, that is, there exists a polynomial time way to verify an answer.

So given a Clique, the graph, weights and target c, we must:


1. Check that all Vertices in Clique are connected to each other
2. Check that the sum of the edges between all vertices is not less than c

You must also prove that this can be done in polynomial time.
Anyone with the link can edit now. Kk thx bai GLHF.

END OF EXAMINATION

You might also like