Problem #1
Preorder traversal 0, 3, 7, 4, 6, 2, 9, 1, 5, 8
Inorder traversal 4, 7, 6, 3, 0, 1, 9, 2, 8, 5
Postorder traversal 4, 6, 7, 3, 1, 9, 8, 5, 2, 0
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
2. +------------+
| Picard |
+------------+
/ \
/ \
+------------+ +------------+
| Crusher | | Riker |
+------------+ +------------+
\ \
\ \
+------------+ +------------+
| LaForge | | Worf |
+------------+ +------------+
/ /
/ /
+------------+ +------------+
| Data | | Troi |
+------------+ +------------+
Only partial credit is 2 out of 4 points if just one node is in the wrong
place.
-------------------------------------------------------------------------------
Problem #3
Method Call Contents of Set Returned
-----------------------------------------------
mystery(grid, 1) [1, 2, 3, 4, 5]
mystery(grid, 2) [4, 6, 8, 9]
mystery(grid, 4) [4, 5, 6, 8]
1 pt for first problem
2 pt for second problem
2 pt for third problem
-1 for order error (just once for the entire problem)
-1 for duplicates (just once for the entire problem)
-1 for missing number
-1 for extra number
-0 for no brackets or no commas
no subproblem can go negative
Problem #4
solution
public String acronymFor(List words) {
String acronym = "";
for (String next : words) {
acronym += next.toUpperCase().charAt(0);
}
return acronym;
}
1 correct header (static is okay)
1 loop over list (can be foreach, iterator, get/size, as long as it traverses
the list so that each string is visited once in the loop)
3 construct and return acronym; there are 5 things to do:
declare local String variable and initialize to empty string
return the local String variable at the end
get the first character of each string
convert that character to its capitalized version
concatenate each capital letter to the local string variable
The points are based on how many of the 5 they do right:
1 at least 2 of these
1 at least 4 of these
1 all 5 of these and the pieces fit together
notes:
-1 if they change the list
Problem #5
solutions
public int oddPathSum() {
return oddPathSum(overallRoot, 0);
}
private int oddPathSum(IntTreeNode root, int sum) {
if (root == null) {
return 0;
} else {
sum += root.data;
int result =
oddPathSum(root.left, sum) + oddPathSum(root.right, sum);
if (sum % 2 != 0) {
result++;
}
return result;
}
}
---------------------------------------------------------------------------
public int oddPathSum() {
return oddPathSum(overallRoot, false);
}
private int oddPathSum(IntTreeNode root, boolean odd) {
if (root == null) {
return 0;
} else {
if (root.data % 2 != 0) {
odd = !odd;
}
int result =
oddPathSum(root.left, odd) + oddPathSum(root.right, odd);
if (odd) {
result++;
}
return result;
}
}
---------------------------------------------------------------------------
public int oddPathSum() {
return oddPathSum(overallRoot, 0, 0);
}
private int oddPathSum(IntTreeNode root, int sum, int count) {
if (root == null) {
return count;
} else {
sum += root.data;
count = oddPathSum(root.left, sum, count);
count = oddPathSum(root.right, sum, count);
if (sum % 2 != 0) {
count++;
}
return count;
}
}
---------------------------------------------------------------------------
public int oddPathSum() {
return oddPathSum(overallRoot, 0);
}
private int oddPathSum(IntTreeNode root, int n) {
if (root == null) {
return 0;
}
n = (n + root.data) % 2;
return n + oddPathSum(root.left, n) + oddPathSum(root.right, n);
}
---------------------------------------------------------------------------
1 public header
1 overall setup: private method returning an int with a root parameter and a
second parameter that can keep track of odd path sum (e.g., sum/boolean),
public method calls private method passing it overallRoot and appropriate
starting value for second parameter, public method returns result of private
method
1 base case for null (tests for this and prevents any NullPointerException)
2 recursive calls
1 their answer includes recursive calls on root.left and root.right
1 correctly traverses the entire tree
2 correctly computes a value that can be used for odd path sum (for these
points, don't worry about whether their tests for odd path sum are correct;
you want to look at the initial call with overallRoot, how they incorporate
root.data, and the recursive calls they are making to see if the pieces fit
together to produce a value that can be tested for odd/even path sum):
1 reasonable attempt
1 correct (requires a recursive call on both left and right, but assume the
tree is traversed correctly)
3 correctly counts odd path sums
1 reasonable attempt: testing for odd path sum and returning a different
value in that case
2 correct (-1 if minor error like obob or counting even path sums)
notes:
* a count field loses the overall setup point if private method has void return
and always loses the 2 counting correctness points
* give to question leader any solutions that change the tree or use extra data
structures (even a string)
Problem #6
solution
public Map>> acronyms(Set> lists) {
Map>> result =
new TreeMap>>();
for (List words : lists) {
String acronym = acronymFor(words);
if (!result.containsKey(acronym)) {
result.put(acronym, new HashSet>());
}
result.get(acronym).add(words);
}
return result;
}
1 header (static is okay)
2 construct and return proper map
1 reasonable attempt: map of strings to sets of lists of strings
1 all correct (correct generics, correct return, map is a TreeMap, used Map
interface for variable, missing parens are a syntax error)
1 loop over set (foreach or iterator)
1 get the acronym for the list (easiest if they call acronymFor)
3 add a new set to map when acronym is first seen
1 reasonable attempt to test for this case
1 reasonable attempt to construct a set that they add to their map (should
be a HashSet, only 1 mistake allowed)
1 all correct (tests whether this acronym is there, adds an entry if it is
new, associates it with a HashSet, correct generics)
2 adds list to existing set assuming key is there
1 reasonable attempt (getting something from the map that they then add to)
1 all correct
Problem #7
solution
public class ClockTime implements Comparable {
private int hours;
private int minutes;
private String amPm;
public ClockTime(int hours, int minutes, String amPm) {
this.hours = hours;
this.minutes = minutes;
this.amPm = amPm;
}
public int compareTo(ClockTime other) {
if (!amPm.equals(other.amPm)) {
return amPm.compareTo(other.amPm);
} else if (hours != other.hours) {
return hours % 12 - other.hours % 12;
} else {
return minutes - other.minutes;
}
}
public int getHours() {
return hours;
}
public int getMinutes() {
return minutes;
}
public String getAmPm() {
return amPm;
}
public String toString() {
String result = hours + ":";
if (minutes < 10) {
result += "0" + minutes;
} else {
result += minutes;
}
result += " " + amPm;
return result;
}
}
1 class header
3 fields declared correctly (1 point per field, -1 if not private, okay to have
extra fields)
2 constructor
1 reasonable attempt to set fields correctly
1 all correct (header, setting fields)
2 get methods (getHours, getMinutes, getAmPm)
1 at least one corect
1 all correct
8 compareTo
2 correct am/pm test (-1 if == versus equals)
3 correct hours test
1 ignoring 12
2 including 12
1 reasonable attempt to handle this case
1 correctly handles this case
1 correct minutes test
2 correct order (am/pm, then hours, then minutes) and header
1 close (at most one transposition, header problem okay for this point)
1 correct order and header
4 toString
1 includes all 3 fields
1 all correct ignoring extra "0"
2 extra 0 included for 1-digit numbers
1 reasonable attempt to handle this case
1 correctly handles this case
Notes:
Give to question leader any solution that involves storing 0 for hour when
it is equal to 12.
There is a PracticeIt problem where you can test compareTo solutions.
Problem #8
solutions
public void makeFull() {
overallRoot = makeFull(overallRoot, 1);
}
private IntTreeNode makeFull(IntTreeNode root, int level) {
if (root != null) {
if (root.left == null && root.right != null) {
root = new IntTreeNode(-level, root, root.right);
root.left.right = null;
} else if (root.left != null && root.right == null) {
root = new IntTreeNode(-level, root.left, root);
root.right.left = null;
}
root.left = makeFull(root.left, level + 1);
root.right = makeFull(root.right, level + 1);
}
return root;
}
---------------------------------------------------------------------------
public void makeFull() {
overallRoot = makeFull(overallRoot, 1);
}
private IntTreeNode makeFull(IntTreeNode root, int level) {
if (root != null) {
if (root.left == null && root.right != null) {
IntTreeNode temp = makeFull(root.right, level + 1);
root.right = null;
return new IntTreeNode(-level, root, temp);
} else if (root.left != null && root.right == null) {
IntTreeNode temp = makeFull(root.left, level + 1);
root.left = null;
return new IntTreeNode(-level, temp, root);
}
root.left = makeFull(root.left, level + 1);
root.right = makeFull(root.right, level + 1);
}
return root;
}
1 overall setup: public header (return is not okay) and private header with a
root parameter and public method calls private method passing it overallRoot
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 1 && all left are like this)
1 root.right = recurse(root.right) (at least 1 && all right are like this)
1 returns root or modified root in all cases
1 root == null case (test for it, do nothing, never get a NullPointerException)
2 correctly computes level
1 level parameter in private method
1 correctly computes the level on each call (tend to lose this for ++)
4 adding new nodes: 1-child cases
1 correct test for one of the 1-child cases
1 correctly constructs a node with the same child as the old root and with
the old root as a child where there was an empty subtree for one case
(should have data that is minus level, but no double jeopardy with level
computation)
1 correct test for second 1-child case
1 correct construction for second 1-child case (can get this if there is a
minor error that lost the first node construction point)
3 severing links for old parent nodes
1 reasonable attempt to sever at least one child link
1 correctly sets old child link to null for one case without losing access
to that subtree
1 correctly sets old child link to null for second case without losing
access to that subtree
2 correct recursive calls are made for 2-child case (left and right)
2 recursive calls are made for 1-child cases (lose these if they set children
to null)
notes:
Give to question leader solutions that avoid x=change(x), that have extra
data structures, that change data fields, that might not be O(n).
If they call 0-argument or 1-argument node constructor, that is a syntax error
first syntax error is free, then -1 per syntax category, max -2
If the severing code doesn't work and causes other problems, give them the
attempt point for severing and then ignore that code.
If they morph nodes, they use both node construction correctness points and all
three severing points.
-------------------------------------------------------------------------------
Problem #9
solution
public LinkedIntList removeAlternatePairs() {
LinkedIntList result = new LinkedIntList();
if (front != null && front.next != null) {
result.front = front;
front = front.next.next;
ListNode current1 = result.front.next;
ListNode current2 = front;
while (current2 != null && current2.next != null &&
current2.next.next != null &&
current2.next.next.next != null) {
current1.next = current2.next.next;
current2.next.next = current2.next.next.next.next;
current2 = current2.next.next;
current1 = current1.next.next;
}
current1.next = null;
}
return result;
}
1 header (lose this if return type is ListNode even if they return a ListNode)
2 constructs and returns other LinkedIntList
1 reasonable attempt (can get this even if they are returning a ListNode)
1 correct (requires call on LinkedIntList constructor, proper return)
2 simples cases: can't get these for no code...each requires a test
1 length 0 case: does nothing and doesn't throw an exception
1 length 1 case: does nothing and doesn't throw an exception
note: should return empty list for each case, -1 once if they return null
3 generous pattern match
1 using curr1/curr2 variables to keep track of a position in each of the
two lists with a loop that changes each
1 resetting at least two "next" fields in a loop
1 a third "next" field is set to null in the loop or a "next" field is set
to null after the loop
12 other cases (could lose 2 points for not setting final node link to null)
2 length 2
1 length 3
1 length 4
1 length 5
2 length 6
1 length 7
1 length 9
1 length 10
1 length 11
1 length 14
notes:
The testing program will tell you if their only mistake is not setting the
final node's link to null for the constructed list (this costs 2 them 2 of the
correctness points).
-1 if they say other when they mean other.front (but only if that raises their
score)
We have a general rule that if you can fix one problem and it suddenly works,
then we make that fix and charge them 5 points. If this gives someone a higher
score, you can grade it that way. But don't spend too much time trying to
figure out their mistakes. A single correction would involve adding or
deleting a single line of code like curr=curr.next or changing a test for
something like curr!=null to be curr.next!=null
Another example of a change would be if they use a name like "curr" when they
have variables with names like "curr1" and "curr2", so we don't know which one
they mean. That would require a 5-point charge to fix a single boolean
expression or a single line of code (you can't fix multiple things this way).
If they call a size method, that can be their -5 mistake (but they can't have a
second -5 mistake).
Any O(n^2) solutions or odd solutions (new nodes, changing data) go to the
question leader.
Stuart Reges
Last modified: Wed Jul 24 17:09:52 PDT 2019