Problem 1: --------- public static int mystery(BinaryTree t, int i) { int n = 0; if (t != null) { if (t.getData() <= i) { n++; } n = n + mystery(t.getLeftSubtree(), i); n = n + mystery(t.getRightSubtree(), i); } return n; } a) The mystery method returns the number of values in the input tree, t, that are less than or equal to i. A good name might be something like countNodes() or nodesLessThanOrEqualTo(). b) The method does a constant amount of work for each node (comparisons, increments, .getData(), etc), and it needs to run once for each node in the tree, regardless of the shape of the tree. There are N nodes, giving O(N) overall. (This is true for *any* tree, whether it's ordered or not.) Problem 2: --------- Recall that Selection Sort makes N passes over the array, and for each pass it does an O(N) "find the smallest" pass over the unsorted portion. Part a) Converting it to sort a list requires that we replace the O(1) array access operations in the "find the smallest" pass with .get() calls, which are O(N) for LinkedLists. Thus we have: For each sorting step: - Find smallest: O(N) comparisons x O(N) cost for each - O(N) for .set() or O(N) for .add()/.remove() calls Inside the loop that's a total of O(N^2)+O(N) --> O(N^2). The loop runs N times, for a total of O(N^3). Part b) If we were to copy to an array, sort it with Merge Sort, and copy back to a list, that would cost: - Copy to array -- O(N) if we use iterator (O(N^2) if not) - Sort array -- O(N log N) - Copy back to list -- N insertions at O(1) cost We *add* all of those costs, which reduces to O(N log N), the largest of the terms. (When creating a list from the sorted array we could make sure we add at the front each time to ensure O(1) insertions.) Problem 3: --------- Here's one way to write it. Note that we need to be careful to check whether the list in a given slot is null or not before checking its length. public int longestChain() { int length = 0; for(List l : table) { // Consider each list if (l != null && l.size() > length) { length = l.size(); // found new winner } } return length; } Problem 4: --------- a) O(N^2): We make a linear pass through the array, but for each value need to make another linear pass. It's true that we might get to stop early on some of those passes, but worst case it's still O(N^2) b) O(N): For each of the N items we need to do an add, but that's a constant time operation on a HashSet. On the second pass, we do a single contains() query for each of the N items, but that's a constant time operation as well. Thus we have 2N, but can drop the constant, 2, when reporting Big-O. c) Making a copy takes O(N) time and sorting it takes O(N log N) time, and then we make a linear pass through and do a binary search for each of the N items. That linear pass is therefore O(N log N) overall (N items, each with an O(log N) search). The total is N + N log N + N log N, or N + 2*(N log N), but after discarding constants and lower-order terms it's O(N log N). d) Storing all items in the BST takes O(N^2) -- N insertions, each of which is O(N) worst case. (The insertions would be O(log N) if the tree were balanced, but we have no guarantee that it is, so worst case they're each O(N)). Then we make a pass looking for mates: For each of the N items we need to do an O(N) check in the BST, so the printing pass is again O(N^2). The total is O(N^2)+O(N^2), which is still just O(N^2).