CS 2110 Learning Objectives
Given some Java code for a loop, possibly with some pieces missing, draw a dot at the points where the loop invariant must hold, and where it might not.
- Must hold before loop - After loop guard - Before next iteration - After loop
From memory, state the "loop checklist" aka "the four loopy questions." In your own words, explain what each question means.
1. Does it start right? (ESTABLISHMENT/INITIALIZATION) - The loop invariant must be true before entering the loop. 2. Does it maintain the invariant? (PRESERVATION) - The loop body must maintain the invariant. After the body is executed, the invariant must still remain true. 3. Does it end right? - The loop invariant must be true just after exiting the loop. The postcondition must be met when the loop invariant is true and the loop guard just became false. 4. Does it make progress towards termination? - The body of the loop must make progress towards exiting the loop. Every repetition of the body must do something to get closer to making the loop guard false
Given the implementation of a recursive function, describe its base case in your own words.
A base case is needed to stop a recursive function from recursing infinitely. A base case is for one special input value that can be computed immediately without any help.
Given a binary tree, state whether it is a valid binary search tree (BST)
Binary Search Tree → All values in the left subtree are less than this node's value & all values in the right subtree are greater than this node's value
Given the size of a binary tree, state its minimum & maximum possible height.
Binary Tree → Each node has at most 2 children Minimum Height → Each node has 2 children Maximum Height → Each node has 1 child
Given a diagram of a tree, state whether it is a binary tree.
Binary Tree → Each node has at most 2 children, distinguished as left & right
Given a diagram of a binary tree, enumerate the nodes visited by an inorder traversal.
Inorder Traversal -Traverse left subtree -Visit self -Traverse right subtree
Among selection sort, insertion sort, merge sort, and quicksort, identify which algorithms are stable, and explain why.
Insertion sort and merge sort are stable algorithms. To be a stable algorithm, the relative order of equal elements must be preserved in the sorting algorithm. Insertion sort is stable because elements only move right-to-left and stop when they hit a duplicate. Merge sort is stable because merging is always left-to-right. Selection sort is not stable because long-range swaps can change order. Since insertion sort and merge sort do not swap elements, their algorithms are stable as the relative order of elements is maintained before and after the sort.
Given a diagram of a tree, circle examples of the following: leaf, parent & child, subtree, root, interior node, siblings, & descendants & ancestors of a given node.
Leaf → A tree node with no children Parent → A tree node that has one or more nodes that descend directly from it. Child → A tree node that descends directly from a node, known as its parent, at the next level in the tree. Subtree → Any node in a tree, together with all of the node's descendants. Root → The node that is at the top of a tree. The root has no ancestor, but it is the ancestor of all other nodes in the tree. Interior Node → A node in a tree that is not a leaf. Siblings → Tree nodes that have a common parent. Decendents → A tree node along the path between node n and a leaf. Ancestors → A tree node along the path between node n and the root.
In your own words, describe the linear and binary search algorithms.
Linear Search → A way of searching an array that examines each array entry in order of occurrence in the array. Searches through the array from front to back to find the item. Binary Search → A way of searching an array that divides the array into two pieces, determines which piece can contain the desired entry, known as the target, & then ignores the other part as it continues the search.
Variant of the above skill → draw the call stack at a given point of execution, or state the maximum depth of recursion.
Maximum Depth of Recursion → Max amount of call frames on stack at once
Given the implementation of a method that employs synchronization, state which object is serving as the mutex.
Mutex → only one thread may hold lock at a time & other threads will block at the start of their synchronized block until the lock is available.
Given two sequences of Java statements that are executed concurrently and that increment a shared int variable with or without synchronization, state which numbers are possible final values for the variable after both sequences have completed execution.
No Synchronization → every possible variation One with Synchronization → every possible variation Both with Synchronization → one expected value
Given a diagram of a tree with children ordered left to right, enumerate the nodes visited by a preorder or postorder traversal.
Preorder Traversal -Visit self -Traverse left subtree -Traverse right subtree Postorder Traversal -Traverse left subtree -Traverse right subtree -Visit self
Given a loop invariant in array range or array diagram notation, state whether it is consistent with the outer loop of selection sort, the outer loop of insertion sort, an insertion procedure for insertion sort, or a partitioning algorithm for quicksort.
Selection Sort Invariant → a[0,i] sorted & a[i+1,a.length] ≥ a[0,i] Selection Sort Outer Loop → i < a.length - 1 - Find the index of the smallest element Insertion Sort Invariant → a[0,i] sorted & a[i+1, a.length] unchanged Insertion Sort Outer Loop → i < a.length Insertion Procedure → j > 0 && a[j - 1] > a[j] Partitioning Algorithm Quicksort → begin <= p && end >= p
Given a diagram of a tree, state its size & height.
Size → The number of nodes in the tree including the root. Height → The number of levels in a tree whose root is at level 1. Alternatively, the number of nodes along the longest path between a tree's root & a leaf.
State the best-case space complexity for selection sort, insertion sort, merge sort, and quicksort.
The best case space complexity for selection sort is O(1). The best case space complexity for insertion sort is O(1). The best case space complexity for merge sort is O(N). The best case space complexity for quicksort is O(logN).
State the best-case time complexity for insertion sort and quicksort and describe the conditions in which it is achieved.
The best case time complexity for insertion sort is O(N). If the array is already sorted, each insert requires only one comparison. Therefore, the overall complexity is linear O(N). The best case time complexity for quicksort is O(NlogN). The best case for quicksort is when the pivot is the median value and each subarray is less than half the size of the original array.
State the worst-case time complexity for selection sort, insertion sort, merge sort, and quicksort.
The worst case time complexity for selection sort is O(N^2). The worst case for selection sort is that the elements are in the reverse order. The worst case time complexity for insertion sort is O(N^2). The worst case for insertion sort is that every element needs to change positions. The worst case time complexity for merge sort is O(NlogN) The worst case time complexity for quicksort is O(N^2). The worst case for quicksort is that the pivot is either the first element or the last element.
Using Big Oh notation, state the time and/or space complexity of a general tree or BST operation in terms of the tree's size or height.
Time Complexity -Must visit every node -Constant amount of work per node -O(size) Space Complexity -Will accumulate stack frames until reaching a leaf -Stack will be popped between left & right subtrees -O(height)
State the worst-case time complexity of a dictionary's "put" and "get" operations if entries are stored in a sorted or unsorted list.
Unsorted List - Put → O(1) - Get → O(N) Sorted List - Put → O(N) - Get → O(logN)
Given a range notation, state the numbers contained in the sequence it identifies. Examples: [1..5], (1..5), a[..5), a[1..]. In the latter examples, a is an array.
[1..5] → 1, 2, 3, 4, 5 (1..5) → 2, 3, 4 a[..5] → a[0], a[1], a[2], a[3], a[4] a[1..5] → a[1], a[2], a[3], a[4]
Given a key's hashcode and the length of a hash table array, state which element of the array the key should be stored under if indices are derived by taking the positive remainder mod the table length.
index = abs(hash % a.length)
Given the contents of a hash table, compute its load factor.
load factor = number of elements/number of buckets