CS62 - Spring 2020 - Class 6

Example code in this lecture

   GradeGenerator
   AsymptoticsExamples
   BinarySearchExamples

Lecture notes

  • admin
       - Darwin part 1 (World and Species)
          - Due Tuesday
       
       - My office hours tomorrow:
          - 10-10:30am
          - 11-11:30am
          - 3-4pm

       - Prof Papoutsaki's office hours

       - Where we are
          - covered most of the "big" new things in Java
          - We'll continue to introduce a few random Java things each class, but we will now transition to the data structures side of things

  • Exceptions wrap-up
       - How to we raise our own exceptions?
          - throws
             - similar to return except must the value after the throws statement must be an exception (actually, something that inherits from "Throwable")
                - Look at: https://www.manishsanger.com/wp-content/uploads/2018/03/Exception-Hierarchy.png

       - Look at the checkRowCol method in the Matrix class from Darwin
          - If we find a bad argument to get/set, we throw a new IllegalArgumentException
             - IllegalArgumentException is a class, so we have to create a new instance before we throw it

  • throws
       - there is another way to handle checked exceptions besides adding a try/catch block
          - let someone else handle it! :)

       - You can add "throws NameOfException" at the end of a method declaration and that indicates to any method that calls you that either 1) you explicitly throw that exception or 2) that you call a method that throws that exception
          - If you do this, you're off the hook for having the catch the exception

       - Look at GradeGeneratorFileThrows class from GradeGenerator code

  • this(...)
       - We'll often have multiple constructors in a class. Why?
          - Allow for different ways of creating the object
          - Often, allow for having versions that specify more details

       - It can be convenient in these cases to call one of the constructors from another constructor
          - there's a special syntax to do this because we can just say new ..., since that would create a whole new instance of the class

       - Look at the Matrix class from Darwin
          - We have two constructors
          - The first one simply calls the second one with the default parameters

       - the "this" call (like a super call), must be the first line in the constructor

  • char
       - one of the other built in types for representing a single character
       - to create them use single quotes
          char c = 'a';

       - returned by some of the String methods, e.g.
          String s = "...";
          char first = s.charAt(0);

  • look at the sum method in AsymptoticsExamples code
       - How long will it take if we pass it an array with 1000 numbers in it? 10,000 numbers?
          - We don't know!
          - We could time it and find out
       - Even if you time it, can you say conclusively how long it will take?
          - No!
          - Variation from run to run
          - Depends on the computer
          - etc.
       - If I tell you the time it took on 10,000 numbers was t. Could you tell me approximately how long it would take on 20,000 numbers?
          - would take about twice as long, i.e., 2t
          - why?
             - does a linear pass through the data
             - doubling the size of the data, means about twice as much work

  • Asymptotics
       - Precisely calculating the actual cost of a method is tedious and not generally useful
       - Different operations take different amounts of time. Even from run to run, things such as caching, etc. will complicate things
       - Want to identify categories of algorithmic runtimes
       - What we really want to do is compare different algorithms
          - Want to know which algorithms will be much worse (or much better) than others

  • Big O
       - We write that an algorithms run-time is O(g(n)) if the run-time can be bounded as n gets larger by some constant times g(n)
       - For example, sum is O(n), i.e. linear

  • look at the lastElement and sumProduct method in AsymptoticsExamples code
       - What do they do?
       - What are their Big O running times?
          - Put another way, how does their run-time grow as you increase the size of the input?
       - lastElement
          - O(1), aka constant
          - no matter how large the array is (assuming .length is a constant time operation) it always does the same amount of work
       - sumProduct
          - O(n^2), aka quadratic
          - for each element, it must do a linear amount of work

  • if we know that sumProduct on an array of size 10,000 take time t. Could you tell me approximately how long it would take on 20,000 numbers?
       - about 4t
          - We can figure this out by plugging our time into the O equation:
             - t time for size of size x array
                g(n) = n^2
                g(10000) = 10000^2 = t
             - doubling the size means:
                g(20000) = 20000^2 = (2 * 10000)^2 = 4 * 10000^2 = 4t
                
                - the time will roughly quadruple if we double the size
                
  • How does Big-O notation allow us to ignore irrelevant details?
       - look at the doubleSum method in AsymptoticsExamples code
          - What is the Big O runtime of this method?
             - O(n)
          - How does it's runtime compare to that of sum?
             - twice as long (calls sum twice)
       - Even though doubleSum is twice as slow as sum, they're still in the same category since they will roughly grow at the same rate

  • Show running time table https://cs.pomona.edu/classes/cs62/lectures/big_O.jpg

  • look at search1 method in BinarySearchExamples code
       - what does this method do?
       - what is the running time, using Big-O notation?
          - depends! sometimes an method/approach always has the same running time
             - look at search1a method in BinarySearchExamples code
          - In general, we'll talk about three different things for a method:
             - best case running time
             - worst case running time
             - average case running time
       - what are the best, worst and average case running times
          - best: O(1), constant, when the example is the first element
          - worse: O(n), linear, when the example is the last element
          - average: O(n), linear, on average, we'll need to traverse half of the elements (~n/2) which is still O(n)

  • look at search2 method in BinarySearchExamples code
       - what does this method do?
          - uses a helper method
          - does the same thing as the previous, but using recursion
       - which version is better?
       - what is the running time, using Big-O notation?
          - same as for the iterative version

  • can we do better than either of these procedures?
       - without any preprocessing of the data, no

  • Last time we played the number guessing game. How were you able to find the number without just listing a bunch of random numbers?
       - When we guessed a number, we were told larger or smaller which allowed us to eliminate a bunch of numbers   

  • what if I told you the data was in sorted order?
       - how do you find information in a phonebook (where the data is in essence, sorted)?