COMP 132 Practice Final Exam 150 points

COMP 132 Practice Final Exam 150 points name: 1. (10 points) Consider implementing a data structure in which elements can be added at either end and a...
6 downloads 0 Views 102KB Size
COMP 132 Practice Final Exam 150 points name: 1. (10 points) Consider implementing a data structure in which elements can be added at either end and also removed from either end. Elements in the middle of the collection can never be accessed. Would it be more efficient (in terms of running time) to implement this structure using a java.util.LinkedList or a java.util.ArrayList? Justify your answer in terms of the running time of each operation. Hint: recall that java.util.LinkedList is implemented as a doubly-linked list, and that the class keeps track of references to both the head and the tail of the list. It would be much more efficient to use a java.util.LinkedList. Adding and removing at the beginning of the list are O(1) (constant time) operations for any linked list, and because LinkedList keeps a reference to the tail of the list, adding at the end is also a O(1) operation. Additionally, because of this reference and because the list is doubly-linked, removing from the end of the list is also O(1) - just use the previous reference to back the tail reference up one position and then sever the link to the last node. For a java.util.ArrayList, adding and removing at the end are O(1) operations, but adding and removing at the beginning require O(n) time. For adding at the beginning, all elements must be shifted right to make room for the new one. For removing at the beginning, all remaining elements must be shifted left to fill the vacated position. 2. Consider sorting an array that is already sorted. (a) (5 points) Can you give a big O bound that is tighter than O(n2 ) for insertion sort when it is applied to a sorted array? Justify your answer. Yes. For a sorted array, the inner loop in insertion sort will never run. The outer loop runs n − 1 times for an array of size n, giving a total running time of O(n). (b) (5 points) Can you give a big O bound that is tighter than O(n2 ) for selection sort when it is applied to a sorted array? Justify your answer. No. Selection sort always performs the same amount of work no matter how its input array is arranged, so O(n2 ) is the tightest possible bound.

1

3. (5 points) For the Environment Simulator Lab, what is the primary advantage of making AnimalType an abstract class rather than an interface? Many of the fields and methods can be defined directly within AnimalType and then just inherited and used in Fox and Rabbit if AnimalType is defined as an abstract class. If AnimalType is an interface, the declarations of the fields and the definitions of those methods must be repeated in both Fox and Rabbit. 4. (5 points) For the Environment Simulator Lab, what would be the primary disadvantage of making AnimalType an ordinary (non-abstract) class rather than an abstract class? (Hint: the GUI code for the lab calls all of the methods declared in the original AnimalType interface.) Since the GUI calls all of these methods, they must all be declared in AnimalType - the GUI calls them through variables of type AnimalType, so methods declared only in subclasses can not be called. If AnimalType is an ordinary (non-abstract) class, it must provide definitions of all of these methods. However, the definitions of many of the methods (notably move, reproduce and ageAndDie) must be significantly different for each of the subclasses - making it very difficult to provide a sensible definition in the superclass. 5. (30 points) The following definition of class Account will be used by a bank for storing account information. Complete the definition of the equals method according to the given javadoc specification. public class Account { private int acctNumber; private double balance; public Account(int initNum, double initBal) { acctNumber = initNum; balance = initBal; } public int getAcctNumber() {return acctNumber;} public double getBalance() {return balance;} /** ordinary accounts do not pay interest */ public double payInterest() {return 0.0;} /** @return whether or not obj is an Account with the same account number and balance as the calling object */ public boolean equals(Object obj) { if (obj instanceof Account) { Account acc = (Account) obj; return acc.getAcctNumber() == acctNumber && acc.getBalance() == balance; } else { return false; } } }

2

Next, complete the definition of the constructor and equals method for the SavingsAccount class, which represents savings accounts (that pay interest). The constructor must initialize all fields (including those inherited from Account), and you are not allowed to add any methods to the Account class. public class SavingsAccount extends Account { private double interestRate; public SavingsAccount(int initNum, double initBal, double interest) { super(initNum, initBal); interestRate = interest; } public double getInterestRate() {return interestRate;} /** @return the interest on this account */ public double payInterest() { return getBalance() * interestRate; } /** @return whether or not obj is a SavingsAccount with the same account number, balance and interest rate as the calling object. For full credit, do NOT use the getAcctNumber and getBalance methods in your answer. */ public boolean equals(Object obj) { if (super.equals(obj) && obj instanceof SavingsAccount) { return interestRate == ((SavingsAccount) obj).getInterestRate(); } else { return false; } } } On the next page, complete the definitions of the addAccount, totalInterest and averageInterestRate methods of the Bank class according to the given javadoc specifications. Note that the signature of the addAccount method is not given - you must provide the parameters and return type for this method. If you need more space, you can use the back of the page as long as you indicate that you have done so.

3

import java.util.ArrayList; public class Bank { private ArrayList accounts; public Bank() {accounts = new ArrayList();} /** the addAccount method can add both ordinary accounts and savings accounts define it here. */ public void addAccount(Account acc) { accounts.add(acc); }

/** @return the total interest paid on all accounts at the bank. No interest is paid on ordinary accounts, but the interest on savings accounts is the balance times the interest rate. For full credit, do not use instanceof in your definition of this method. */ public double totalInterest() { double result = 0; for (Account acct : accounts) { result = result + acct.payInterest(); } return result; } /** @return the average interest rate for all savings accounts at this bank. bank has no savings accounts, throw an appropriate exception. */ public double averageInterestRate() { int num = 0; double total = 0; for (Account acct : accounts) { if (acct instanceof SavingsAccount) { num++; total = total + ((SavingsAccount) acct).getInterestRate(); } } if (num == 0) { throw new IllegalStateException("Error: no savings accounts!"); } else { return total / num; } } }

4

If the

6. (15 points) Write a recursive static method findLargest that takes an ArrayList of Comparable objects as a parameter and returns Comparable - the largest of the objects in the ArrayList as measured by the compareTo method. You can assume that the ArrayList contains at least one element. The findLargest method itself must not have any parameters other than the one specified above, but you are allowed to define and use a helper method, and findLargest itself need not be recursive if the helper method is recursive. You are NOT allowed to use any loops or fields for this problem, and you are NOT allowed to modify the ArrayList. public static Comparable findLargest(ArrayList ar) { return findLargest(ar, ar.get(0), 1); } private static Comparable findLargest(ArrayList ar, Comparable large, int start) { if (start >= ar.size()) { return large; } else { if (large.compareTo(ar.get(start)) < 0) { large = ar.get(start); } return findLargest(ar, large, start + 1); } }

5

7. (15 points) Complete the definition of the following StringStack class so that the push, pop and isEmpty methods work as expected for a stack. You are NOT allowed to add any additional fields. The running times of the isEmpty and pop methods must be O(1). Any attempt to pop an empty stack must result in an IllegalStateException. Recall that the java.util.ArrayList class defines the following methods: • size() - which returns the size of the ArrayList • remove(index) - which removes the element at the specified index • add(index, element) - which adds the specified element at the specified index • add(element) - which adds the specified element at the end You are NOT allowed to use any other methods of the java.util.ArrayList class. import java.util.ArrayList; public class StringStack { private ArrayList elems; public StringStack() { elems = new ArrayList(); } /** push a new String on top of the stack */ public void push(String data) { elems.add(elems.size(), data); // equivalently: elems.add(data); } /** remove and return the String on top of the stack throw an IllegalStateException if the stack is empty */ public String pop() { if (isEmpty()) { throw new IllegalStateException("Error: popping empty stack!"); } else { return elems.remove(elems.size() - 1); } } /** return whether or not the stack is empty */ public boolean isEmpty() { return elems.size() == 0; } }

6

8. (30 points) Complete the following definition of class IntList, which implements a linked list of ints. You must declare the necessary field(s) and complete the definitions of the constructor, addBefore, removeAfter and size methods according to the given javadoc specifications. The running times of your addBefore, removeAfter and size methods must be O(n) for a linked list with n elements. You are not allowed to use any of the classes and interfaces from the java.util package (including the Iterator interface). For example, after the following code sequence: IntList il = new IntList(); il.addBefore(3, 1); il.addBefore(2, 3); il.addBefore(5, 4); il.addBefore(1, 5); il.addBefore(6, 5); il.removeAfter(6); il.removeAfter(2); the list il should contain (in order) 2, 1 and 6, and the call il.size() should return 3. public class IntList { private static class Node { public int data; public Node next; public Node(int data, Node next) { this.data = data; this.next = next; } } // declare your field(s) here private Node head; /** initialize an empty list of ints */ public IntList() { head = null; } /** @return the number of elements in the list */ public int size() { int len = 0; Node tem = head; while (tem != null) { len++; tem = tem.next; } return len; }

7

/** add a Node containing dat to the list immediately before the first Node * containing target. If target does not occur in the list, add a Node * containing dat to the end of the list */ public void addBefore(int dat, int target) { if (head == null || head.data == target) { head = new Node(dat, head); } else { Node tem = head; while (tem.next != null && tem.next.data != target) { tem = tem.next; } tem.next = new Node(dat, tem.next); } } /** remove the Node immediately after the first Node containing target. If target does not occur in the list or is the last element of the list, throw an appropriate exception */ public void removeAfter(int target) { Node tem = head; while (tem != null && tem.data != target) { tem = tem.next; } if (tem == null || tem.next == null) { throw new IllegalArgumentException("Error: list does not contain " + target); } else { tem.next = tem.next.next; } } }

8

9. (10 points) Complete the definition of the following method according to the given javadoc specification. Additionally, you must use an iterator for all manipulation of the ArrayList - you are not allowed to access it in any other way. You can assume that the Song class has a getYear() method that returns the year of the song. Note that class ArrayList implements the Iterable interface. /** remove all songs older than oldestYear from the arraylist */ public static void removeOldies(ArrayList playList, int oldestYear) { Iterator sIter = playList.iterator(); while (sIter.hasNext()) { if (sIter.next().getYear() < oldestYear) { sIter.remove(); } } } 10. (5 points) Give a tight big O bound on the worst case running time of your implementation of the removeOldies method, and briefly justify your bound. O(n2 ). Removing a song via the iterator is still O(n) because all following songs must be shifted left, and in the worst case each of n songs is removed, giving an overall running time of O(n2 ).

9

11. (15 points) What output is displayed when the main method of class ExceptionTest is run? public class Exception1 extends Exception { public Exception1() {} public Exception1(String msg) {super(msg);} } public class Exception2 extends RuntimeException { public Exception2() {} public Exception2(String msg) {super(msg);} } public class ExceptionTest { public static String spindle(int dat) throws Exception1 { try { if (dat == 1) { return "one"; } else if (dat == 2) { throw new IllegalArgumentException("bad arg"); } else if (dat == 3) { throw new Exception1("bad"); } else if (dat == 4) { throw new Exception2("worse"); } else { throw new NullPointerException(); } } catch (NullPointerException npe) { return "null pointer"; } finally { System.out.println("finally done"); } } public static void mutilate(int dat) { try { System.out.println(spindle(dat)); } catch (NullPointerException npe) { System.out.println("caught NPE"); } catch (IllegalStateException ise) { System.out.println("in an illegal state"); } catch (RuntimeException re) { System.out.println("caught runtime exception"); } catch (Exception e) { System.out.println("caught exception"); } } public static void main(String [] args) { mutilate(1); mutilate(2); mutilate(3); mutilate(4); mutilate(5); } }

10

finally done one finally done caught runtime exception finally done caught exception finally done caught runtime exception finally done null pointer

11