Problem #1
Preorder traversal 4, 5, 2, 9, 3, 7, 6, 0, 1, 8
Inorder traversal 2, 9, 5, 3, 7, 4, 0, 6, 8, 1
Postorder traversal 9, 2, 7, 3, 5, 0, 8, 1, 6, 4
2 points each, only partial credit is if the sequence matches the right answer
other than one single error (missing number, wrong number, transposed pair)
problem #2
+------------+
| Karl |
+------------+
/ \
/ \
/ \
+------------+ +------------+
| Chris | | Simon |
+------------+ +------------+
/ \ \
/ \ \
/ \ \
+------------+ +------------+ +------------+
| Anton | | John | | Zoe |
+------------+ +------------+ +------------+
/
/
/
+------------+
| Zach |
+------------+
Only partial credit is 2 out of 4 points if just one node is in the wrong
place.
Problem #3
solution
public int oddDepthSum() {
return sum(overallRoot, 1);
}
private int sum(IntTreeNode root, int depth) {
if (root == null)
return 0;
else if (depth % 2 == 0)
return sum(root.left, depth + 1) + sum(root.right, depth + 1);
else
return root.data + sum(root.left, depth + 1) +
sum(root.right, depth + 1);
}
1 correct public header && private header with root parameter && public method
returns result of calling private with overallRoot
1 works (returns 0) when overallRoot is null
2 base case when root == null for nonempty trees
1 reasonable attempt to test for this case
1 correct (no NullPointerException, returns 0 whenever root is null)
6 recursive cases
1 their answer includes recursive call on root.left and recursive call on
root.right
3 adds root.data to their sum when level is odd
2 attempt (must pass extra int parameter updated with +1 or ++ or
extra boolean parameter updated with not)
1 correct
2 actually works to compute the sum (requires previous attempt)
Problem #4
solution
class TeamData implements Comparable {
private String name;
private int solved;
private int totalTime;
private int problems;
public TeamData(String name, int problems) {
this.name = name;
this.problems = problems;
this.totalTime = 0;
this.solved = 0;
}
public void success(int problem, int time) {
solved++;
totalTime += time;
}
public String toString() {
return name + " solved " + solved + " of " + problems + " in "
+ totalTime + " minutes";
}
public int solved() {
return solved;
}
public int time() {
return totalTime;
}
public double percentCorrect() {
return 100.0 * solved / problems;
}
public int compareTo(TeamData other) {
if (solved != other.solved)
return other.solved - solved;
else
return totalTime - other.totalTime;
}
}
1 class header
4 fields (1 point each, -1 once if not private, okay to have extra field(s))
2 constructor
1 correct header
1 all fields set apropriately (can rely on defaults for totalTime, solved)
2 solved and time methods
1 reasonable attempt (at least one method completely correct or two methods
that are each partially correct)
1 all correct
2 percentCorrect method
1 reasonable attempt (exists, divides solved by problems)
1 correct
2 success method
1 reasonable attempt (updates at least one of the two fields)
1 all correct
2 toString
1 reasonable attempt (exists, includes at least 2 of the 4 fields)
1 all correct, including format
5 compareTo
1 primary comparison is for problems solved
1 compares times when problems solved is equal
2 correct comparison for problems solved (most people will miss this)
1 all other aspects correct (header, time comparison)
Problem #5
solution
class ExtendedTeamData extends TeamData {
private int[] times;
private int[] failed;
public ExtendedTeamData(String name, int problems) {
super(name, problems);
times = new int[problems];
failed = new int[problems];
}
public void success(int problem, int time) {
times[problem] = time;
super.success(problem, time + failed[problem] * 20);
}
public void fail(int problem) {
failed[problem]++;
}
public String detailString() {
String result = "solved:";
for (int i = 0; i < times.length; i++)
if (times[i] > 0) {
result += " " + i + " (" + times[i];
if (failed[i] > 0)
result += "+" + failed[i] * 20;
result += ")";
}
return result;
}
}
1 class header
2 correct use of data structures: these should be difficult to get, but then
we're going to assume that whatever they do works. They should lose both of
these points if one or both of their data structures are in their TeamData
class.
1 Know how to use at least one such structure. Requires:
* appropriate structure (int[], Map, List)
* at least one correct initialization of their structure somewhere
* at least one correct put into the structure somewhere
* at least one correct get from their structure somewhere
1 Really know how to use structures (always use them correctly). Requires:
* two appropriate structures
* fail method includes at least one put
* success method includes at least one put
* detailString method includes at least one get and correct loop bounds
4 fields
2 field to store count of failed attempts (map, array, list)
1 declared
1 initialized in a proper place (can be outside constructor)
2 field to store problem times (map, array, list)
1 declared
1 initialized in a proper place (can be outside constructor)
1 constructor header and call on super(name, problems)
2 fail method
1 exists, correct header
1 records failed attempt for given problem (requires failed field)
5 success method
4 calling super.success
1 correct call on super.success when no failed attempts for problem
3 adds penalty to time when there are failed attempts for a problem
1 attempt (e.g., increment private superclass time)
2 correct (penalty included in call on super.success)
1 records time (requires time field)
5 detailString method
1 loop over problems
1 append problem # and time if solved (requires solved/times field)
2 appends penalty, if any (requires failed field)
1 correct test to append penalty only if there is one
1 appends correct string
1 overall structure: method header, result string that starts with
"solved:", return result string
Problem #6
solution
public void stretch() {
overallRoot = stretch(overallRoot);
}
private IntTreeNode stretch(IntTreeNode root) {
if (root != null) {
root.left = stretch(root.left);
root.right = stretch(root.right);
if (root.left != null && root.right == null)
root = new IntTreeNode(1, root, null);
else if (root.left == null && root.right != null)
root = new IntTreeNode(1, null, root);
}
return root;
}
1 public header
1 private header with a root parameter and public method calls private method
passing it overallRoot
1 works (does nothing) when overallRoot is null (based on test)
5 used x = change(x) (if you think they didn't need it, show to quest leader)
1 overallRoot = recurse(overallRoot)
1 private method has return type IntTreeNode
1 root.left = recurse(root.left) (at least one && all left are like this)
1 root.right = recurse(root.right) (at least one && all left are like this)
1 private method returns an IntTreeNode in at least one case
3 base case when root = null for nonempty trees
1 attempt (tested this case)
2 correct (tree not changed in this case)
3 recursively stretching subtrees
1 attempt: calls on stretch(root.left) and stretch(root.right)
2 correct: stretch in all appropriate cases, no order problems
6 adding new nodes
1 attempt to test for this case (test if left or right is null)
1 correct tests (has to exclude leaf case)
2 construct a new node in this case (requires test attempt)
1 call on node constructor is correct (includes 1, places old node in
correct place)
1 always reset root to new list node (or returns it)
Problem #7
solution
public void markMultiples(int n) {
if (n <= 0)
throw new IllegalArgumentException();
if (front != null) {
ListNode current = front; // tricky Stuart sets current before
// resetting front
if (front.data % n == 0)
front = new ListNode(0, front);
while (current.next != null) {
if (current.next.data % n == 0) {
current.next = new ListNode(0, current.next);
current = current.next.next;
} else
current = current.next;
}
}
}
1 header
2 exception
1 attempt
1 correct
1 works (does nothing) for empty list (requires test)
6 correctly inserts at front of list
2 attempt: test if front.data % n == 0 && (make a new node || reset front)
2 correct: correctly inserts 0 at front of list when front.data % n == 0
2 test front.data % n == 0 && reset front && current set to OLD front
(for a prev/curr solution, prev must be set to old front)
10 inserts in rest of list
2 generous: have a loop with a curr, test for null, curr = curr.next
--------------------------------------------------------------------------
all of the remaining points require basic idea
2 basic idea: test for .data % n == 0 && construct new node
2 looking one ahead (curr.next) or using a prev/curr approach && correct
loop bounds (-1 if obob)
2 correct insertion of 0; one of these (or equivalent):
if (current.next.data % n == 0)
current.next = new ListNode(0, curr.next);
if (current.data % n == 0)
prev.next = new ListNode(0, curr.next);
2 special update for curr or prev/curr if you insert (nobody should end up
pointing to the new node)
Recursive solutions go to question leader.
In this question we will make limited use of a dangerous grading concept known
as "transformation." For example, what if a student has a perfect solution
other than the fact that they were missing "current = current.next" inside
their loop? The criteria often award them 0 points because nothing works. But
perhaps the student just made a stupid mistake and actually knows quite a bit.
We will keep a table of transformations that you can apply. You can apply only
ONE transformation unless you get the approval of the question leader.
Standard transformations:
Penalty Problem
------------------------------------------------------
3 test for multiple is (number / n == 0)
3 test for multiple is (number % 2 == 0)
3 loop update is current = current.next.next;
5 loop is missing current = current.next
Stuart Reges
Last modified: Fri Sep 16 16:16:07 PDT 2011