CS307 Fall 2009 Final Exam Suggested Solution and Criteria: 1 1.5 Each, differences in capitalization and spacing okay. On Big O no O() okay. A: 37 / \ 13 42 / \ -12 101 B: 17, 19, 25, 10, 20, 30, 7, 15 C: 19, 10, 25, 17, 20, 7, 30, 15 D: 10, 25, 19, 7, 15, 30, 20, 17 E: No. F: valid binary search tree using values between 1 and 10. No repeats. G: 130 H: ANI I: O(N^2) J: O(N) K: O(N) L: O(N^2) M: O(NlogN) N: O(N^2) O: O(N^2) P: Answers in range 30 - 50 inclusive are correct. Q: 9 11 R: 6 S: HashSet Add, access, and remove are average case O(1). With TreeSet they are average case O(logN). (-1 if HashSet is answer, but bad explanation.) T: Variables must have a box and arrow. 2. Suggested Solution: Using look ahead public boolean removeFirst(E obj) { int oldSize = size; if(first != null) { // special case, first contains obj if(obj.equals(first.getValue()){ first = first.getNext(); size--; } else { // general case Node temp = first; while(temp.getNext() != null && obj.equals(temp.getNext().getValue())) temp = temp.getNext(); if(temp.getNext() != null){ // found it! temp.setNext(temp.getNext().getNext()) size--; } } } return oldSize != size; } Using trailer public boolean removeFirst(E obj) { int oldSize = size; if(first != null) { // special case, first contains obj if(obj.equals(first.getValue()){ first = first.getNext(); size--; } else { // general case Node leader = first.getNext(); Node trailer = first; while( leader != null ){ if( obj.equals(leader.getValue()) ){ // found it! trailer.setNext(leader.getNext()); size--; } else { trailer = leader; leader = leader.getNext(); } } } } return oldSize != size; } Two pass algorithm public boolean removeFirst(E obj) { int oldSize = size; Node temp = first; int position = 0; while(temp != null && !obj.equals(temp.getValue()){ position++; temp = temp.getNext(); } if( temp != null ){ // found it so remove it if(position == 0) first = first.getNext(); else{ temp = first; for(int i = 1; i < position; i++) temp = temp.getNext(); // now temp on node before first occurrence of obj temp.setNext(temp.getNext().getNext()); } size--; } return oldSize != size; } Grading: Update first correctly if first node contains obj: 2 points search list for obj: attempt: 2 points correct: 5 points (-2 if OBOE or NPE or doesn't stop at correct location, -5 if doesn't actually move) check elements equal to obj: 2 points (-1 if ==) remove first node that contains obj from list if present: 3 return correct answer: 1 point 3. public MorseCodeTree(Map codes){ root = new BNode(); Iterator it = codes.keySet().iterator(); while(it.hasNext()){ char letter = it.next(); addHelper(letter, codes.get(letter)); } } private void addHelper(char letter, String code) { BNode temp = root; for(int i = 0; i < code.length(); i++){ // go correct direction. build child if necessary if( code.charAt(i) == '.'){ if(temp.getLeft() == null) temp.setLeft(new BNode()); temp = temp.getLeft(); } else{ if(temp.getRight() == null) temp.setRight(new BNode()); temp = temp.getRight(); } } // temp pointing at node for letter temp.setValue(letter); } Create root correctly: 2 points get iterator from keyset: 1 point use iterator to access each value in map: attempt: 2 points correct: 2 points For each key, value pair: traverse to correct location, going right or left attempt: 2 points correct: 4 points build new nodes as necessary: attempt: 1 point correct: 4 points add letter to leaf node: 2 points If destroy tree via last path: -7 4. public String decode(String encodedMessage){ String result = ""; boolean good = encodedMessage.length() > 0; BNode temp = root; for(int i = 0; i < encodedMessage.length() && good; i++){ char ch = encodedMessage.charAt(i); if(ch == '.') // go left, check to ensure exists if(temp.getLeft() == null) good = false; else temp = temp.getLeft(); else if(ch == '-') // go right, check to ensure exists if(temp.getRight() == null) good = false; else temp = temp.getRight(); else // ch is an asterisk, check on letter if(temp.getValue() == null) good = false; else{ result += temp.getValue(); // move back to start temp = root; } } return good ? result : null; } start at root: 1 point loop through string: 2 points go left or right as appropriate: attempt: 2 points correct: 3 points. (must ensure node exists) at asterisk check data null or not: 2 points if !null concat letter to message: 2 points reset to root: 2 points return correct value: 1 point 5 private class HashIterator implements Iterator{ private int conPos; private int arrayListPos; private int numToGet; private boolean removeOK; private HashIterator(){ numToGet = size; // for other vars default values correct } public boolean hasNext(){ return numToGet > 0; } public E next(){ assert hasNext(); removeOK = true; // may have nulled out due to remove if(container[conPos] == null || container[conPos].size() == arrayListPos){ // move to the next valid array list conPos++; while(container[conPos] == null) conPos++; arrayListPos = 0; } numToGet--; return container[conPos].get(arrayListPos++); } public void remove(){ assert removeOK; container[conPos].remove(--arrayListPos); if(container[conPos].size() == 0) container[conPos] = null; size--; } } Instance vars: track current position in container: 2 points track current position in current arraylist: 2 points way to track hasNext: 1 point constructor: 1 point hasNext: 4 points next: 6 points remove: 4 points