CS302 Final Exam - Answers and Grading

James S. Plank - December 10, 2013

Question 1:

Part 1: With selection sort, you should be swapping the smallest element with the first element at iteration 0, and the second-smallest element with the second element at iteration 1.

With insertion sort, iteration 1 will sort the first two elements, and iteration 2 will sort the first three elements.

It's possible for the output to be both.

Part 2: The median of the first, middle and last element is 619. So, we swap that to the front:
619, 983, 036, 783, 734, 186, 494, 469, 251
We set l = 1 and r = 8. The elements at those pointers are in the wrong partition, so we swap them:
619, 251, 036, 783, 734, 186, 494, 469, 983
We increment l until we get to an element that is too big: l=3. And we decrement r until we get to an element that is too small: r=7. And we swap:
619, 251, 036, 469, 734, 186, 494, 783, 983
One more increment and decrement. l = 4 and r = 6. Swap:
619, 251, 036, 469, 494, 186, 734, 783, 983
Increment l until it equals 6. Decrement r until it equals 5. You're done. Swap elements 0 and 5. Here's the final answer:
186, 251, 036, 469, 494, 619, 734, 783, 983


Part 1: 12 points -- two per part.

Part 2: 6 points -- rubrick as follows:

Question 2: Dynamic Programming

You need to add a cache. You need to test it in the beginning of gc(), and whenever you return, you need to add the return value to the cache before you return. You don't need to do this in the first return statement, because there are no recursive calls before that first return statement.

How you index the cache is a concern, because you need to index it both by the string and by zero. In my answer code, I convert them both into a string using a stringstream. However, you could have an array of two caches -- one for zero = 0, and one for zero = 1.

You cannot use a vector indexed on s.size(), because the string changes from call to call (with news).

Here is an answer.


Question 3: Network flow

You were asked to process an augmenting path through a graph while doing network flow. That means you need to figure out the residual flow in the path, and then subtract it from the residual, add the reverse flow to the residual, and add the flow to the flow graph.

There is a subtlety in adding the flow to the flow graph -- if there is flow in the reverse edge, you need to take flow out of the reverse edge, and then if there is any left, you add it to the flow of the non-reverse edge.

void Graph::Process_Augmenting_Path(vector <Edge *> path)
  int i, f;
  Edge *e, *r;

  /* Figure out the flow in the path */

  f = path[0]->residual;
  for (i = 1; i < path.size(); i++) {
    if (path[i]->residual < f) f = path[i]->residual;

  /* Add flow to the flow graph (which means you may have to reduce flow
     on a reverse edge.  Also process the residual -- add flow to the
     reverse edge's residual, and subtract it from the edge's residual.  */

  for (i = 0; i < path.size(); i++) {
    e = path[i];
    r = e->reverse;

    if (r->flow >= f) {
      r->flow -= f;
    } else {
      e->flow = (f - r->flow);
      r->flow = 0;
    e->residual -= f;
    r->residual += f;


Points were allocated roughly as:

Question 4: Running Time

Because each node's adjacency list is ≤ 10, |E| = O(n). Thus, things like O(|V| + |E|) become O(n), and O(|V|log(|E|)) become O(n log n).


1.5 points per answer. There was a little partial credit: Here are the individual answers -- red is wrong, yellow is right:

Question 5: Graph Algorithms