Algorithm Design Foundations Solutions
Algorithm Design Foundations Solutions
1 Hour
9
1 Month
9
log n
210 10300000
23.610 1010
106
n log n
105
3.6 109
n2
1012
1.3 1019
109
12
1 Century
12
22.610 100.810
6.8 1024
15
9.7 1030
2.6 1012
3.12 1015
101 1
15
23.110 1010
1014
1000
n3
6 104
1.6 106
5.6 107
100
2n
1500
14000
1500000
19
31
41
51
n!
12
15
17
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
i=1
i=1
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
log2 i/geq
i=1
which is (n logn).
i= 2 +1
log2
n n
n
= log2 ,
2 2
2
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
2
that is, we use 4 taste testers. Suppose that only test 2 is positive. Given the
structure of the tests, we can infer that the 5th bottle B4 is the poisoned one.
When n is not a power of 2, there are generally more that one possible test
structures. They all can determine the poisoned bottle, but the king should choose
that collection of tests that have the least number of 1s (why?)...
Why is the king not smiling? No, its not because the rumour about the queen
- everybody believes she organized this!... The king is unhappy because all the
bottles of wine (some of them were really old) had to be opened.
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
array A
1
1
1
1
1
1
1
0
1
1
1
1
1
1
1
0
1
1
1
1
1
1
0
0
1
1
1
1
1
1
0
0
1
1
1
1
0
0
0
0
1
1
1
0
0
0
0
0
1
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
Algorithm NumberOfOnes(A):
Input: An 2D array n n A with elements 1s and 0s as described.
Output: The total number of 1s.
N0
j0
for i n 1 to 0 do
while j n 1 A[i, j] = 1 do
N N +i+1
j j+1
return N
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
2
Algorithm replaceAtRank(r,e):
if r < 0 r size() then
throw InvalidRankException
o A[( f + r) mod N]
A[( f + r) mod N] e
return o
Algorithm insertAtRank(r,e):
s size()
if s = N 1 then
throw VectorFullException
if r < 0 r size() then
throw InvalidRankException
if r < 2s then
for i f , ( f + 1) mod N, ..., ( f + r 1) mod N do
A[(i 1) mod N] A[i]
A[( f + r 1) mod N] e
f ( f 1) mod N
else
for i l, (l 1) mod N, ..., (l s + r + 1) mod N do
A[(i + 1) mod N] A[i]
A[(l s + r + 1) mod N] e
l (l + 1) mod N
Algorithm removeAtRank(r):
s size()
if isEmpty() then
throw VectorEmptyException
if r < 0 r size() then
throw InvalidRankException
o elemAtRank(r)
if r < 2s then
for i ( f + r 1) mod N, ( f + r) mod N, ..., ( f + 1) mod N, f do
A[(i + 1) mod N] A[i]
f ( f + 1) mod N
else
for i (l s + 1) mod N, (l s) mod N, ..., (l 1) mod N, l do
A[(i 1) mod N] A[i]
3
l (l 1) mod N
return o
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
2
Algorithm eulerTour(Tree T , Position v):
state start
while state 6= done do
if state = start then
if T.isExternal(v) then
left action
below action
right action
state = done
else
left action
state on the left
v v.le f tchild
if state = on the left then
if T.isExternal(v) then
left action
below action
right action
state = from the left
v v.parent
else
left action
v v.le f tchild
if state = from the left then
below action
state on the right
v v.right
if state = on the right then
if T.isExternal(v) then
state = from the right
left action
below action
right action
v v.parent
else
left action
state on the left
v v.le f t
if state = from the right then
right action
if T.isRoot(v) then
state done
else
if v is left child of parent then
state from the left
else
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
2
if u 6= NULL then
return u
{See if there is a deepest leaf in the right child}
u DeepestLeaf(T ,T .rightChild(v),H,d + 1)
return u
Algorithm findDiameter(T ):
Input : a tree T
Out put : The diameter of T
H depth(T ,T .root())
v DeepestLeaf(T ,v,H,0)
if v = T .root() then
return 0 { if deeps leaf is just the root node, diameter is 0}
Lmax 0
x 1 {x: number of nodes visited}
while v 6= T .root() do
{Assign y to be the length of the path going to the sibling}
y height(T ,T .sibling(v))
{See if we have found a new longest path}
if x + 1 + y > Lmax then
Lmax x + 1 + y
{Climb up the tree one step}
x x+1
v T .parent(v)
return Lmax
The running time of the algorithm is linear. Both depth(T ,v) and height(T ,v)
have complexity O(Sv), where Sv is the size of the subtree rooted at v. depth(T ,v)
is called from the trees root once, so its time complexity is O(n). height(T ,v)
is called for each sibling on our way up to the root, so, in total, it adds an O(n)
time complexity. DeepestLeaf also has linear worst case time complexity, for it is
essentially a pre-order tree traversal. Finally, the leaf-to-root path traversal adds a
linear time complexity.
We can improve on this algorithm, however. Note that the above algorithm
can visit all the nodes in the tree twice, once to find the deepest node, and once to
3
find the height subtrees. We can combine these two operations into one algorithm
with a little bit of ingenuity and recursion. We observe that given a binary tree Tv
rooted at a node v, if we know the diameters and heights of the two subtrees, we
know the diameter of Tv . Imagine we took a path from the deepest node of the
left subtree to the deepest node of the other subtree, passing through v. This path
would have length = 2 + height(Tv, Tv .leftChild(v)) + height(Tv , Tv .rightChild(v)).
Further, note that this is a longest path that runs through the root of Tv , since the
height of the left and right subtrees is simply the longest path from their respective
roots to any of their leafs. Therefore, the longest path in Tv is simply the maximum
of longest path in the found in Tv s left and right subtrees, and the longest path
running through v. These observations give rise to the following algorithm. For
convenience, we denote the return type of this algorithm to be in the form (h, d)
where h and d represent height and diameter respectively, and are accessed using
the h() and d() methods.
Algorithm Diameter(T ,v)
Input : a tree T and a node in that tree v
Out put : a (h, d) pair
if T .isExternal(v) then {Base case}
return (0, 0)
{Get the return pairs of the left and right subtrees}
L Diameter(T , T .leftChild(v))
R Diameter(T , T .rightChild(v))
{Find the height of this subtree}
H max(L.h(),R.h()) + 1
{Find the longest path length}
P L.h() + R.h() + 2
return (H, max(L.d(), R.d(), P))
Since this algorithm visits each node in the tree exactly once, and performs a
constant amount of operations at each node, it follows that this algorithm runs in
O(n)
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
2
Algorithm size():
c0
for i 1, 2, ..., S.size()1 do
if S.elemAtRank(i)6= NULL then
c c+1
return c
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
39
20
16
44
88
12
23
13
94
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
16
11
39
44
88
12
23
13
94
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
23
20
16
39
44
94
12
88
13
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
62
"
Z
"
Z
"
52
JJ
44
50
BB
C
C
17
C
C
54
78
@@
C
C
58
JJ
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
78
"
Z
"
Z
"
44
JJ
17
88
J
J
J
50
S
C
S
C
48
54
C
BB
C
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
34
"
5 12
"
"
"
6
Z
Z
Z
Z
15
6
S
S
345
12 15
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
@
@
@
@
@
@
@
@
@
@
@
@
C
E
C
E
C
E
E
E
E
C
E
C
C
E
E
E
E
E
E
E
E
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
2
{we considerthree cases}
hT heightofT
hU heightofU
if hT = hU then {case 1}
V new tree
V .Insert(V .root(),MaxKeyT ,MaxElemT )
V .Child(V .root(),1) T .root()
V .Child(V .root(),2) U .root()
return V
if hT > hU then {case 2}
v M ostLeftRight(T ,T .root(),hT hU 1,f alse)
T .Insert(v,MaxKeyT ,MaxElemT )
T .Child(v,Type(v)+ 1) U .root()
T .Restructure(v)
return T
if hT < hU then {case 2}
v M ostLeftRight(U ,U .root(),hU hT 1,true)
U .Insert(v,MaxKeyT ,MaxElemT )
U .Child(v,1) T .root()
U .Restructure(v)
return U
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
2
{compute the height of the tower}
ctosses 0
while (random() < 1/2) do
ctosses ctosses + 1
height 1
current tople f t
{find height of skip list}
while (below(current) 6= null) do
current below(current)
height height + 1
{ Insert new levels if necessary and find the first level to insert at}
if (height < ctosses) then
for i 1 to ctosses height do
oldtople f t tople f t
tople f t new Item(,null)
after(tople f t) new Item(,null)
below(tople f t) oldtople f t
below(after(tople f t)) after(oldtople f t)
insertat below(tople f t)
else
insertat tople f t
for i 0 to (height ctosses 1) do
insertat below(insertat)
{ Now do SkipSearch, inserting before going down }
oldnewnode null
while (insertat 6= null) do
while(key(after(insertat)) k) do
insertat after(insertat)
newnode new Item(k,e)
after(newnode) after(insertat)
if (oldnewnode 6= null) then
below(oldnewnode) newnode
after(insertat) newnode
oldnewnode newnode
insertat below(insertat)
Algorithm removeElement(k)
current tople f t
while (below(current) 6= null) do
current below(current)
while key(after(current)) < k do
current after(current)
if after(current) = k then
tmp after(current)
after(current) after(after(current))
delete tmp
Note that the insertion has O(log(n)) expected time (for the same reasons that
SkipSearch has O(log(n))) expected time.
An alternative realization of insertItem could involve the use of a stack. As
we perform SkipSearch, we push into a stack every element that we access. Once
we are at the bottom of the structure, we start tossing the coin and as long as
the flip is coming up heads we insert a copy of the inserted element. We track
any after(p) reference that needs be updated by performing a pop operation of
the stack. Any below(p) reference is handled by storing the last copy added to the
tower. Depending on when the flip is coming up tails, the stack may not become
empty or we may need add new levels. The details are left as an exercise.
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
.
.
.
.
@
@
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
?
?
?
?
?
?
A
-
6
6
6
6
C
D
6
6
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
2
over incident edges. For all these extra variables we assume that there is a mechanism for setting and getting the corresponding values (in constant time). Method
NextNeighbor(G,v) returns that neighbor u of v that will be next visited (that is, the
corresponding edge has not been traversed from v to u and u is not the entrance
node of v) or NULL if no such node can be visited.
Algorithm Traverse(G):
v G.aVertex()
VISITED(v) true
ENTRANCE(v) NULL
u NextNeighbor(G,v)
DONE
e v false
while DONE do
if VISITED(u) then
VISITED(u) true
ENTRANCE(u) e
w NextNeighbor(G,u)
if w = NULL then
if u = v then DONE true
else
Report(u,ENTRANCE(u))
u ENTRANCE(u)
else
Report(u,w)
uw
Algorithm NextNeighbor(G,v):
if EDGE IT(v).hasNext() then
o EDGE IT(v).nextObject()
u G.opposite(v, o)
if u = ENTRANCE(v) then
return NextNeighbor(v)
else return u
else return NULL
The running time of the algorithm is O(n + m). Each edge is clearly traversed (reported) twice and at each node, the decision about what is the next
node to be visited, is made in constant time.
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
2
its perent in the discovering tree of DFS). We then simulate the algorithm for
homework 7a, problem 2: starting from any node, we perform a blind traversal,
where we do not cross any label edge unless we are forced (there are no other way
to leave the current vertex).
We give the pseudo-code that describe the algorithm. Instead of walking
blindly, we assume that each vertex keep an iterator OUT EDGE IT of the outgoing incident edges and in this way edges are traversed in a systematic way (and
thus, we do not have to label them). Also, each vertex stores an edge reference
LAST EDGE; it is a reference to an edge (the one labeled by the DFS traversal)
that must be traversed only if no other option is available. Finally, instead of per
graph G , which is graph G having each edge with a reversed direction. We then
reverse all edges (to switch back to the graph G ) but keep the labeling.
Algorithm EulerTour(G):
for all vertices v do
OUT EDGE IT(v) G.outIncidentEdges(v)
LAST EDGE(v) NULL
3
NextVertex(G,u)
The time complexity is clearly O(n + m): the edge labeling takes linear time
(using DFS in graph G ) and each edge is traversed exactly once and the decision
about which edge to traverse next is made in constant time.
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
```
``2`
``
` C
```
```
` D
3 ``
Suppose we wish to find the shortest path from start = A to goal = D and we
make use of the proposed greedy strategy. Starting at A and with path initialized
to A, the algorithm will next place B in path (because (A, B) is the minimum
cost edge incident on A) and set start equal to B. The lightest edge incident
on start = B which has not yet been traversed is (B, D). As a result, D will be
appended to path and start will be assigned D. At this point the algorithm will
terminate (since start = goal = D). In the end we have that path = A, B, D, which
clearly is not the shortest path from A to D. (Note: in fact the algorithm is not
guaranteed to find any path between two given nodes since it makes no provisions
for backing up. In an appropriate situation, it will fail to halt.)
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
2
Complexity (this has not been asked for): If we maintain U nknown as a heap,
then there are n = |V | ExtractM ax operations on it and upto m = |E| changes to
the values of elements in the heap. We can implement a data structure which
takes O(log n) time for each of these operations. Hence, the total running time is
O((n + m) logn).
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
that G has only positive weights), but we need to slightly modify the algorithm (as it is presented in the textbook), so that it is applicable to directed
graphs. The modifications should be straightforward: in the relaxation step,
2
2am f1 9pm
12am
f3
f2
10pm
4am
a1
a2
8am
6pm
10am
2pm
f6
a3
a4
12pm
12pm
f5
f4
f7
10pm
a5
9pm
6am
6pm
f8
a6
2pm
Figure 0.1: Graph used to reduce a flight scheduling problem to a shortest paths
problem.
we only consider edges with orientation from the previously selected vertex
to some other vertex. Finally, we need keep track (mark) the shortest path,
so we include a parent-child relationship to the visited nodes (value p).
Algorithm F lightS chedu ling(a, b, t):
constru ct graph G
v fi rst vertex on circle(a) representing time t or after t
D[v] 0
4
initialize f light sequence to nil
while (city 6= a) do
append incoming f light(city) to f light sequence
assign to city the departu re city of incoming f light(city)
reverse f light sequence and ou tpu t
The algorithm essentially performs Dijkstras Shortest Path Algorithm (the
cities are the vertices and the flights are the edges). The only small alterations are that we restrict edge traversals (an edge can only be traversed at a
certain time), we stop at a certain goal, and we output the path (a sequence
of flights) to this goal. The only change of possible consequence to the
time complexity is the flight sequence computation (the last portion of the
algorithm). A minimum time path will certainly never contain more that m
flights (since there are only m total flights). Thus, we may discover the path
(tracing from b back to a) in O(m) time. Reversal of this path will require
O(m) time as well. Thus, since the time complexity of Dijkstras algorithm
is O(m log n), the time complexity of our algorithm is O(m log n).
Note: Prior to execution of this algorithm, we may (if not given to us) divide
F into subsets F1 , F2 , . . . , FN , where Fi contains the flights which depart from
airport i. Then when we say for each flight f F such that a1 ( f ) = x,
we will not have to waste time looking through flights which do not depart
from x (we will actually compute for each flight f Fx ). This division
of F will require O(m) time (since there are m total flights), and thus will
not slow down the computation of the minimum time path (which requires
O(m log n) time).
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons
Algorithm Design
M. T. Goodrich and R. Tamassia
John Wiley & Sons