CMSI 2120
Final Exam Preparation

How to Prepare

Students best prepare for a final when they have certain things:

I would suggest going over the outline and concept review below, making sure you understand each topic by going back over the course notes and the relevant sections in the textbook (if any) and associated course readings, where applicable. But don’t just re-read, cram, and highlight; test yourself with well-crafted, meaningful, and helpful questions. Hopefully you’ve been doing some spaced repetition learning along the way.

It may also be helpful to browse many of the course notes pages on material we did not cover. There is a ton of good stuff there. Sometimes this extra material might expose you to ways in which the basic material you did learn can be used in practice.

Glance over the course textbook, especially in the intro and summary sections for the languages we covered in class. It is filled with stuff I like to think about, and since I will be writing the final, well, it never hurts to have just a little more comfort with the things I feel are important.

Do reinforcement and practice problems.

Course Outline

Reviewing this outline will jog your memory. We had fun didn’t we?

  1. DATA STRUCTURES AND ALGORITHMS BIG PICTURE
    1. The Study of Data Structures and Algorithms
      1. Why are they important
      2. Why are they studied together
      3. Connected through data types
    2. Data Types
      1. First approximation: set of values
      2. Better: sets of values plus operations
      3. All about behavior
    3. Data Structures
      1. Three building blocks: arrays, objects, links
      2. Arrays and objects can be nested inside each other
      3. Links allow the same object to be used in multiple places
      4. Null links require great care to manage (Billion Dollar Mistake)
  2. THE JAVA PROGRAMMING LANGUAGE
    1. Bootcamp
      1. Making waves (Getting started)
      2. Coin flipping (final, printing, random numbers)
      3. Egg counting (console reading, parseInt, try-catch, formatting)
      4. Elementary school vibes (command line args, arrays, fields and methods, static, throw)
      5. Day of the week (import, java.time, Locales, ?:)
      6. Nonsense sentences (lists, maps, joining strings)
      7. JShell interlude (BigInteger, string operations, code points, more on arrays and collections)
      8. Small countries (sets, splitting strings, loops, break)
      9. Taking a chance (building your own classes from scratch, multiple-file apps)
      10. How does this even work? (Unit testing, JUnit 5, Assertions)
      11. Playing cards (records and arrays)
      12. Talking animals (inheritance, polymorphishm, abstract classes and methods)
    2. Basics
      1. Structure of a command line application
      2. Writing trivial apps with public static void main(String[] args)
      3. Types: primitives (8 of them) and reference types (5 ways to make them)
      4. Variables and type inference
      5. Printing
      6. Numbers
        1. Integers vs Floats
        2. Precision and accuracy
        3. Operations, both built in and from class Math
      7. Booleans
        1. && and ||
        2. ?:
      8. Strings
        1. Made up of char values
          1. chars are not really characters
          2. .charAt, .length, .subsstring, and .indexOf often produce unexpected results
          3. In general, you need to work with code points
        2. " for single-line strings, """ for multi-line strings
        3. isEmpty, isBlank, strip, startsWith, endsWith, contains, repeat, replace, +
        4. String.valueOf, Integer.parseInt
      9. Characters and Unicode code points
      10. Objects
        1. What they are for
        2. Every value in Java is either a primitive or an object
        3. Fields and methods
        4. Dot notation
        5. Some methods are mutators, some are not
      11. Classes
        1. How to design software around classes
        2. Identity vs equality
        3. Java objects always accessed through references
        4. Record classes
          1. Pure awesomeness
          2. Immutable
          3. Automatically get private final fields, accessors, value-based .equals, hashCode, and toString.
          4. Can define a constructor if you want, which is good for validating arguments
        5. null and all its nastiness
        6. Enum classes
        7. Interfaces
          1. Basically represent behaviors
          2. All fields are automatically public and static and final (you don’t have to mark them as such, they just are)
          3. Methods are automatically public
          4. Methods are either (1) abstract, (2) static, or (3) default
          5. Generally are implemented by classes
      12. Statements
        1. Empty statements, assignment statements, calls
        2. If and switch
        3. For and while
        4. break, continue
        5. return
        6. try, throw
      13. Arrays
        1. Fixed size, cannot grow or shrink
        2. Mutable
        3. Indexes start at 0
        4. Not very many operations (e.g., no index-of, no swap)
        5. A few operations in Arrays, such as Array.equals(a,b) and Arrays.toString(a)
      14. Lists
        1. So many variations possible
        2. Modifiable or unmodifiable
        3. Fixed-size or variable-size
        4. Array-based or link-based
        5. Lots of built-in methods
        6. List.of makes unmodifiable lists
        7. For modifiable lists, use new ArrayList<type> or new LinkedList<type>
        8. More operations in Collections
        9. Generally preferred to arrays
        10. Cannot contain primitives, only objects
      15. Maps
        1. Key-value pairs are called entries
        2. Modifiable and unmodifiable versions possible
        3. For modifiable maps, use new HashMap<type> or new TreeMap<type>
        4. Lots of built-in operations
        5. Cannot contain primitives, only objects
      16. Exceptions
    3. Advanced (not covered early in class but picked up later as needed)
      1. When to use public and private
      2. Abstract classes
      3. Inheritance
      4. Polymorphism
      5. Generics
      6. Arrays are covariant, Collections are invariant
      7. Sealed classes and interfaces
      8. Nesting classes (e.g., nodes)
  3. DATA STRUCTURES FROM SCRATCH
    1. Stacks
      1. LIFO, with push and pop
      2. Implementations: bounded array, singly-linked chain, expandable array
      3. Push and pop operate at top of stack only
      4. In linked implementation, nodes can be immutable
      5. Time needed for push and pop not influenced by size of stack
    2. Queues
      1. FIFO, with queue and dequeue
      2. Implementations: bounded array, singly-linked circular chain, expandable array
      3. Enqueue at back of queue, dequeue at front
      4. Bounded array uses “modular indexing”
      5. Much more complex implementation than stacks
      6. Nodes in linked implementation generally not immutable
      7. Time needed for push and pop not influenced by size of stack
    3. Lists
      1. Unrestricted sequences, can add and remove anywhere at all
      2. Large number of operations
      3. Good mutable implementation is circular doubly-linked
      4. Good immutable implementation is singly-linked using a sealed interface with two subtypes: EmptyList and ListNode
      5. Recursion common in immutable singly-linked version
  4. MATHEMATICAL FOUNDATIONS
    1. Math
      1. What math is
      2. Symbols and notation
      3. Sets
      4. Tuples
      5. Relations
      6. Functions
      7. Lambda Notation
      8. Numbers
      9. Logarithms
    2. Algorithm Analysis
      1. What exactly are we analyzing?
      2. Why we measure relative, not absolute, time
      3. The idea of abstract operations
      4. Choosing $n$, the input size
      5. Several examples of determining $T(n)$
      6. The common (and some not-so-common) complexity classes
      7. Asymptotic Analysis (O, $\Theta$, $\Omega$)
      8. The effects of increasing input size
      9. The effects of a faster computer
    3. Recursion
      1. What it is and why it is important
      2. Recursion in Nature, Math, Language, Art, Music, Computer Science
      3. Recursive algorithms and functions
      4. Efficiency concerns with recursion
      5. Tips for when using recursion is okay
      6. The usefulness of recursive datatypes
    4. Sorting
      1. Demos and interactive widgets
      2. Classification by Mechanism
        1. By Exchange (e.g., Bubble, Cocktail, Gnome, Comb)
        2. By Selection (e.g., Selection, Heap)
        3. By Insertion (e.g., Insertion, Shell, Tree)
        4. By Merge (e.g., Merge)
        5. By Distribution (e.g., Radix, Counting)
        6. Hybrids (e.g., Tim, Intro)
      3. Classification by Complexity
        1. $\Theta(n^2)$ comparison sorts
        2. $\Theta(n \log n)$ comparison sorts
        3. $\Theta(1)$-ish distribution sorts
        4. Concurrent sorts
        5. Impractical sorts
      4. The surprising fun of the impractical sorts
        1. Stooge
        2. Bogo and Bozo and Bogogo
        3. Bad
        4. Worst
        5. Miracle
    5. Search
      1. How to think about search
      2. Binary Search
      3. Sets
      4. Maps (Dictionaries)
      5. How sets and dictionaries are alike
      6. Representations of sets and dictionaries
  5. ADVANCED DATA STRUCTURES
    1. Trees
      1. Three main application areas
        1. Networks: for minimal connectivity
        2. Hierarchy Modeling
        3. Search: to make it logarithmic!
      2. Uses in networks (Free Trees)
        1. Minimal Connectivity applications
        2. Base vocabulary: Node, Edge, Size, Path, Path Length, Simple Path
      3. Models of hierarchies (Oriented Trees)
        1. Hierarchy applications: geography, books, HTML, source code, file systems
        2. Other representations: tables, Venn diagrams, outline, string with nested parentheses
        3. New vocabulary: root, leaf, internal node, parent, child, sibling, ancestor, descendant, width, height, depth, level, degree, 0-node, 1-node, 2-node, k-node
        4. Traversal
          1. Breadth-First (Implemented with Queue)
          2. Depth-First (Implemented with Stack or written Recursively)
        5. Ordered Trees
          1. Binomial
          2. Fibonacci
          3. k-ary
            1. Have a natural representation
            2. If dense, these can go in arrays
            3. Good to know about complete trees
            4. There is some elegant math around binary trees
            5. In full trees there are more trees on the last level than there are in the sum total of nodes on all levels above
      4. Tree-based implementations of sets and dictionaries (Search Trees)
        1. Classic Search Trees
          1. Set elements go fully in the nodes themselves
          2. Elements must be mutually comparable
          3. Also called navigable sets/maps or sorted sets/maps
          4. Kinds
            1. (a,b), B, B+
            2. Naive Binary Search Trees
            3. Good Binary Search Trees: AVL, Red-Black, Splay, Scapegoat
        2. Prefix/Radix Trees (Tries)
          1. Set elements spread out among nodes
          2. Elements need NOT be mutually comparable
          3. Technically, elements are stored in paths (neat, right?)
          4. Kinds
            1. Tries with huge numbers of children
            2. Tries over a restricted alphabet (usually binary)
            3. “Ternary Search Trees” (not a great name, but whatever)
    2. Hash Tables
      1. For sets and dictionaries where elements are not compared with each other
      2. Apply a hash function to an object to find the index it should be at
      3. Need to be able to either avoid or deal with collisions
      4. Hash functions
        1. need to give good distribution (should not have clustering)
        2. need to run efficiently
      5. Best case for add, lookup, and remove is $\Theta(1)$
      6. Worst case for add, lookup, and remove is $\Theta(n)$
      7. On average, with good hash function and a good-sized table, essentially $\Theta(1)$
      8. Hash table resizing
        1. Expensive, but only extremely rarely done
        2. Rule of thumb: double hash table size when around 70% full
      9. Collision resolution strategies
        1. Linear Probing
        2. Quadratic Probing
        3. Cells store linked lists
        4. Cells store binary search trees
    3. Bitsets (sadly, not covered this semester)
    4. Heaps
      1. For priority queues
      2. Complete binary search trees with each node having higher priority than its children
      3. Internal operations are sift up and sift down
      4. Add and remove are both $\Theta(\log n)$

Things Learned in the Course

You want value from your education, right? So think about the major themes of that course. Think about what you learned. Think about things you can take from the course to be better in everything you do.

We learned a lot of things:

Suggested Practice Problems

Do the course practice problems that relate to the course material over the semester.

Also, test yourself on the problems from the earlier exams in the course. Copy out the problems but not the answers. The next day, test yourself on them. Practice spaced-repetition if possible.

What To Expect

There will be 20 multiple choice and multi-select problems.

The final will be “open” all week, from Monday, December 12, through Friday, December 17 You may take the exam in whatever 2 hour period in this window is convenient for you. You are bound to the LMU Honor Code.

The exam will be on BrightSpace and have multi-select and multiple-choice problems—the kinds you are used to from previous exams.

A list of the main areas of concern for each of the 25 problems will appear on Slack, so stand by for those!