Spring 2023 Exam #2 Solutions ----------------------------- Problem #1: ----------- The mystery method takes an integer value, n, and a Stack of integers, and returns a separate stack that's identical to the input except that all copies of n have been removed. The input stack is left unchanged. A good name might be something like removeValue. Problem #2: ----------- Here's one way to do part a: newNode.next = head.next.next; // Make 2's node point to 8 as next head.next.next = newNode; // Make 4's node point to 2's as next See after_change.png for diagram of changes resulting from the code in part b. It makes the first two nodes share the 6-sided die, and creates a "loop" from 8's node back to 4's node. In other words, if we were to print the list, we'd see an infinite sequence starting with [6,6,8,6,8,6,8,...]. Problem #3: ----------- Here's a version that *almost* works. It has a single loop that traverses the values from the queue, copying them to the output. At the appropriate spot, the code inside the loop *also* copies the new name into the output. This version won't insert into an empty queue though -- the loop never runs, so we never insert the new name. Worse than that, that comparison will potentially be true for *lots* of the strings in the input queue, so this method will potentially add name more than once. public static Queue insert(Queue names, String name) { Queue output = new LinkedList(); while(!names.isEmpty()) { String first = names.remove(); if (name.compareTo(first) < 0) { output.offer(name); // Add name if it's time } output.offer(first); // Always add current name to output } return output; } Here's a revised version that properly inserts into queues of any length. We run one loop to copy the values that come before the new name, then insert the new name, and follow up with a second loop to copy remaining items to the output. This works even if the new name ends up being the first or last item in the queue. (One loop or the other just won't run.) public static Queue insert2(Queue names, String name) { Queue output = new LinkedList(); while(!names.isEmpty() && name.compareTo(names.peek()) >= 0) { output.offer(names.remove()); // Copy items to output } output.offer(name); // Add the new name while(!names.isEmpty()) { output.offer(names.remove()); // Copy remaining items } return output; } Problem #4: ----------- a) ArrayList b) We do log2(N) iterations of Binary Search, each of which involves a constant amount of work since .get() is constant time. That gives a O(log2(N)). c) If we used a LinkedList we'd still do log2(N) iterations of Binary Search, but each of those would do O(N) work since .get() is O(N) for LinkedLists. That would give O(N x log2(N)). d) Big-O for processWord() is O(N) if we choose lists wisely. For each call, we do: 1) Binary Search on words list to find proper position ==> O(log2(N)) 2) Check to see if word is in the list ==> O(1) 3) Possible insertion of new word ==> O(N) 4) Possible insertion (or .set()) of new counter ==> O(N) The cost of steps 1-4 is O(N), since it grows more quickly than the other terms. That underestimates the impact of using binary search though, since step #1 happens *many* more times than steps 3 & 4 in practice.