A 90 minute closed book examination.
Question 1 
Lower bounds.
In a comparisonbased model of computation,
give the decision treebased lower bound (without working
out logarithms!) for the number of comparisons
to solve the following problems:

Solution 
As we have a binary decision tree, the
solution is ceiling(log_2 N) where N
is the number of different solutions.
Think about this more generally.
Let A be a sorted list of n elements,
let B be a sorted list of m elements,
and let C be an unsorted list of k elements.
For the first question, we need to merge A and C.
The merged list of length n+k is totally
determined if each element of C in turn
were to know its position. The first element has
n+k choices, the second n+k1 and so forth until n+1.
Thus, the number of solutions is
N = (n+k)(n+k1)...(n+1) .To merge A and B into a list of length n+m, we only need to specify the positions the elements of B (as a group!) occupy in it. There are (n+m choose m) such choices. Thus, N = (n+m)! / n! m!To get back to specific numbers, for part A, the answer is ceiling(log_2 (11x12))=8. For part B, the answer is ceiling(log_2 (27!/20!7!))=19. 
Question 2 
Recurrences, trees.
We are given a complete position tree with
a fanout of 41 (41 children per node).
Given that there are n nodes in all, answer these
questions:

Solution 
Let h be the height of the tree. Two of a number of
equivalent answers for part A. are:
h = ceiling(log_41 (40n+1)) 1 h = floor(log_41 (40n39))Verify that these formulas are exact for all n (even n=1). To get the first solution, count the number of nodes in each full level, and obtain these bounds: 1 = 41 + ... + 41^(h1) < n <= 1 + 41 + ... + 41^hfrom which we derive (41^h 1)/40 < n <= (41^(h+1) 1)/40 41^h < 40n+1 <= 41^(h+1) .Now take logarithms to the base 41. Part B: consider the standard array implementation of a kary position tree. A moment's thought shows that the number of leaves is nparent[n], where parent[n] is the index of the parent of node n. Now, parent[n]=floor((n+39)/41) (this is the proper generalization of the formula for binary trees we saw in class). The answer is nfloor((n+39)/41), or, equivalently, floor((40n39)/41). For part C, the recurrence is T_n = 2 T_(n/41) + 1which by the master theorem yields T_n = theta(n^a), where a = log_41 (2). 
Question 3 
Stacks, queues, algorithms.
Given are the following operations on any
kind of element:

Solution 
We will stick all elements and partial infix subexpressions
in queues.
It is helpful to write a short additional procedure
JOIN(a,b,op) that takes queues a and b (these could
be singleelement queues holding operands,
or multielement queues holding subexpressions),
and an operator op
as input and returns a queue holding (,
the elements of a, op ,
the elements of b, and ).
JOIN(a,b,op): MAKENULL(Q) JOINQUEUE(Q,MAKEQUEUE("(")) JOINQUEUE(Q,a) JOINQUEUE(Q,MAKEQUEUE(op)) JOINQUEUE(Q,b) JOINQUEUE(Q,MAKEQUEUE(")")) RETURN(Q)The main algorithm proceeds as follows: MAKENULL(S) (S is an auxiliary stack of queues) while not EMPTY(Q) do: x=DEQUEUE(Q) (x is an element) if ISOPERATOR(x) then b=POP(S) a=POP(S) PUSH(JOIN(a,b,x),S) else PUSH(MAKEQUEUE(x),S) I=TOP(S) (I is the infix queue)Note: it is important to treat partially reconstructed pieces of the infix expression as we would individual elements. This can be achieved by treating all such pieces and all individual elements as queues (everyone is the same for the law). The JOIN operation puts the parentheses in the right places so that operator precedence is a nonissue. At the end, the stack S has only one element, the queue I. Technical note: JOINQUEUE(Q,MAKEQUEUE(op)) is equivalent to ENQUEUE(op,Q), but JOINQUEUE(Q,a) cannot be replaced by an ENQUEUE operation. It is also inefficient to enqueue all elements of the queue "a" individually as "a" may have many elements. For efficiency, JOINQUEUE is needed here. 
Copyright © 2000 Luc Devroye. Email: luc@cs.mcgill.ca.