NAME: EE 322C Spring 2009 Final READ THIS FIRST. Please use the back side of each page for scratch paper. I will not give credit for illegible answers (and I reserve sole judgment for what is “legible”). The exam is out of 100 points, not all questions are equally hard or take equally long to complete. Good luck! 1. (6 pts) Add Java statements to the following program such that the program prints the numbers from 1 to 100 (inclusive). class Foo { public int v; public static void main(String[] args) { Foo[] x; // Add code here for (int k = 0; k < 100; k += 1) { System.out.println(x[k].v); } } } 2. (6 pts) What is output by the following program? class Foo { public int x = 1; public static int y = 1; public Foo() { x = x + 1; y = y + 1; } public static void main(String[] args) { Foo f; for (int k = 0; k < 10; k += 1) { f = new Foo(); } System.out.println(f.x); prints:________ System.out.println(f.y); } } prints:________ 3. Consider the following problem. We have an array of N Strings. There may be duplicates in the array. We want to print the string in the array that appears most frequently. If there is a “tie” for the most frequently appearing string, then we want to print the smallest string of those that occur with maximal frequency (smallest here means “comes first in dictionary order”). I’ve identified two approaches (questions 3 and 4) to this problem. In the first approach, I place all the strings into a map. Each key/value pair in the map uses the string as the key, and the number of times that string appears in the array as the value. So, if the word “apple” appears in the array 3 times, then the key value pair (“apple”, 3) will be placed into the map. After building the map, I iterate through the map and find the string that has the largest count (and is smaller than all other strings with that count). The questions for this program are listed on the next page. String findMode(String[] strings) { // Part A of the algorithm Map m = new HashMap(); for (int k = 0; k < strings.length; k += 1) { if (m.containsKey(strings[k])) { // a duplicate Integer count = m.get(strings[k]); m.put(strings[k], new Integer(count.intValue() + 1); } else { // string has not been seen before m.put(strings[k], new Integer(1)); } } // end of part A // Part B of the algorithm String ret = null; int max_freq = 0; Iterator p = m.iterator(); while (p.hasNext()) { MapEntry e = (MapEntry) p.next(); String s = e.getSting(); Integer f = e.getValue(); if (retValue == null || f.intValue() > max_freq || (f.intValue()== max_freq && s.compareTo(ret) < 1)) { max_freq = f.intValue(); ret = s; } } // end of part B return ret; Q3 (18 pts) Continued: Answer the following questions for findMode1 a. What is the worst case time complexity for Part A of the algorithm? b. If we assume simple uniform hashing, what is the time complexity of Part A? c. If we were to use a TreeMap in place of a HashMap, what would the time complexity be for Part A? d. What is the time complexity for Part B assuming the HashMap implementation guarantees a load factor between 0.5 and 0.8 for all values of N larger than 8. e. What would the time complexity be for Part B if a TreeMap were used in place of a HashMap? f. If all the strings in the array turn out to be the same (e.g., the arrays contains N copies of “apple”), which data structure is more effective, a HashMap or a TreeMap (or are they the same)? Please restrict your considerations to time complexity. 4. In the alternative approach for finding the mode in the array, I sort the array of strings first. Then, I perform a sequential scan of the sorted array, knowing that any duplicates will now be stored consecutively. I count the frequency that each string appears and return the first string that has the maximal number of duplicates. The Java standard library provides an O(N log N) sort function called Arrays.sort(). (questions are on the next page) String findMode2(String[] strings) { Arrays.sort(strings); String ret = strings[0]; int max_freq = 1; int count = 1; for (int k = 1; k < strings.length; k += 1) { if (strings[k] != strings[k-1]) { count = 1; } else { count += 1; } if (count > max_freq) { ret = strings[k]; max_freq = count; } } return ret; Q4 Continued: answer the following questions for findMode2 a. (3 pts) What’s the time complexity of findMode2? b. (4 pts) Under what circumstances is this approach superior to the version that uses a Map? Mark each of the following statements with a T (for true) or F (for false). i. The sort approach is better than using a HashMap in the worst case ii. The sort approach is better than using a HashMap in the common case iii. The sort approach is better than using a TreeMap in the worst case iv. The sort approach is better than using a TreeMap in the common case 5. (15 pts) Multiple Guess and short answer. a. A garbage collector will i. Identify all the the objects referenced by null pointers, and overwrite those null objects with new objects. ii. Identify objects that my program is no longer using, and overwrite those old objects with new ones. iii. Identify objects that my program can no longer access, and overwrite those unreachable objects with new ones. b. Constructors are not static functions in Java because i. The purpose of a constructor is to initialize a single object. Thus, constructors will always need this in order to perform their basic function. ii. Constructors have no return value. iii. Constructors in Java are invoked when calling “new”. Thus, the memory is always on the heap and can’t be statically allocated. iv. Who says that constructors can’t be static? Of course they can. c. The keyword “private” in java is used to help i. Undisciplined programmers resist the temptation to hand-optimize code using their knowledge of the detailed design of other modules in the system. ii. The compiler to better optimize programs so that they’ll run faster iii. The virtual machine to optimize memory so that (private) data takes less space. iv. Sun Microsystems to optimize profits since almost all major software in use today requires the the basic protection of private and public d. Which of the following will guarantee “simple uniform hashing”? i. Use the built-in hashCode() function (i.e, don’t write your own) ii. Write a hashCode() function that computes the XOR of all of the bits inside the object iii. Force the load factor to be 1.0 iv. None of the above 6. Label the following tree as described in parts a and b. a. (5 pts) Insert the numbers 1-16 into the following tree such that it is a Binary Search Tree b. (5 pts) Put a “B” inside each node that would be black for the tree to be a red-black tree 7. (10 pts) Consider the following classes, and indicate what the main program will print. I’ve put in at least one error (sorry, I know that makes the question a bit tricky). The error is not supposed to be a semicolon missing, or anything idiotic like that, but an error related to inheritance and how inheritance works in Java. Anyway the error (or errors) will prevent the program from compiling (which obviously prevent it from running). I want you to identify the error, circle it, and explain the error. Then, I want you to fill in the rest of the program as if the line(s) containing error(s) had been removed from your program. class Cake { public void eat() { System.out.println(“sawdust”); } } class ChocCake extends Cake { public void eat() { System.out.println(“yummy”); } } class ChocTort extends ChocCake { public int layers; public ChocTort(int v) { layers = v; } } class PoundCake extends Cake { public void eat() { System.out.println(“you are what you eat”); } } class Question5 { public static void main(String[] stupid_param) { Cake w = new Cake(); Cake x = new ChocCake(); Cake y = new ChocTort(); Cake z = new PoundCake(); w.eat(); // prints: ________________________ x.eat(); // prints: ________________________ y.eat(); // prints: __________________________ System.out.print(y.layers); // prints: _______________________ z.eat(); // prints: _____________________________ } } 8. (5 pts) Write the function successor for the following binary search tree. Recall that successor must return the Node that contains the next larger value from the BST. class BST { static class Node { Comparable item; Node parent; Node left; Node right; } Node root; // root of the BST; static Node findSmallest(Node p) { while (p.left != null) { p = p.left; } return p; } static Node successor(Node p) { } 9. (5 pts) Write an iterator() class and an iterator() function for the BST. Your iterator must provide a next() and hasNext() function. Please do not write remove() for your iterator. For full credit, your iterator must be as simple as possible. Don’t forget to write both the class and the BST.iterator() function. 10. (6 pts) Early in the semester we implemented a Set data structure using an array in which we kept the elements sorted at all times. Some people argue that Set data structures should be built using Red-Black trees. Assume the operations that can be performed on a Set are insert (i.e., “add”), find (i.e., “contains”), and intersection (i.e., retainAll). Complete the following table by adding the time complexity for each type of Set data structure, assuming that there are N elements in the set(s). (red-black) Tree-based Set (sorted) Array-based Set Insert Find Intersection 11. (6 pts) Complete the following table by filling in the time complexity for each of the following operations assuming the data is contained in either a LinkedList or an ArrayList data structure as indicated. LinkedList ArrayList Bubble Sort Binary Search Remove Smallest 12. (6 pts) The ArrayList class has a fast “append” function because most of the time there is extra “capacity” at the end of the array – i.e., there is room for more elements than are currently in the data structure. With each of the following approaches indicate the total time complexity to append N items (PLEASE, TOTAL TIME for all N, not the time for just one append). a. The extra capacity is always 0. That is, always allocate the minimum amount of storage to hold the elements in the data structure. b. The extra capacity is always between 0 and 100 – that is, when the capacity is increased, the extra capacity is increased to exactly 100, but then not increased again until it drops to zero. c. Ensure that the extra capacity is always between 0 and size() (where size() is the number of elements currently in the data structure). As before, the capacity is only increased when it reaches zero, and the amount of extra capacity is always set to size() when it is increased.