1/86
Looks like no tags are added yet.
an entry on the call stack representing a single method call that is in progress; holds call's parameters, local variables, and where to resume in the caller when it returns
In what order are frames added to and removed from the call stack?
LIFO
What is a call tree, and how is it different from the call stack?
A call tree shows the complete history of all function calls. call stack only shows the calls in progress at one moment, (a single path)
What are the steps (7) that happen behind the scenes when a function is called?
main calls a(), a calls b(), and b is currently running. What is on the call stack, from top to bottom?
True or false: any iterative function can be written recursively.
True
what is the syntax used for Comparable comparisons vs Comparator comparisons?
this.compareTo(o); comparator.compare(o1, o2)
When is memoization not helpful?
When the subproblems don't overlap
What happens when an array-backed list runs out of space?
It allocates a brand new, larger array (1.5x size) and copies all of the elements from the old array into it, which takes O(n) time.
Why would expanding an array-backed list by a very large amount be a bad design?
waste of space
What is the complexity of inserting at an arbitrary position in an array-backed list, and why?
O(n). bc shifting
What is the complexity of removing by reference ("remove this object") from an array-backed list, and why?
O(n). The list first has to linearly search for the object, and then shift the elements after it to the left to close the gap.
What is the complexity of removing by idx from an array-backed list, and why?
O(n). The lookup is O(1), but shifting the elements to the left is O(n), since on average about n/2 elements after index i must be shifted
What is the complexity of removing the last element of an array-backed list, and why?
O(1) bc no shift
If list is an ArrayList containing [3, 2, 1], what does list.remove(1) do?
list.remove(1) defaults to removing by position, so the result is [3, 1]. To remove the value 1, use list.remove(Integer.valueOf(1)), leaving [3, 2].
T/F: An ArrayList can store primitive and reference types
False, ArrayList can only store objects (no primitive types)
What’s the default capacity of an ArrayList
10 (unless you explicitly pass a capacity to the constructor)
What is the time complexity of appending to a singly-linked list with/without a tail pointer, and why?
with: O(1) bc the tail pointer gives direct access to the last node
without: O(n) bc you have to start at the head and travers every node to find the last one
What is the time complexity of prepending to a linked list, and why?
O(1). The head pointer gives direct access to the first node, so the new node just points to the old head and becomes the new head
What is the time complexity of removing by position ("remove the object at index i") from a linked list (doubly-linked vs singly-linked), and why?
O(n) for both. You have to scan the list to find the node at position i (and the node before it) before you can unlink it.
What is the time complexity of removing by reference to a node ("remove this node") from a singly-linked list? doubly linked list?
O(n), unless the node is the head. Each node in a singly-linked list only stores a reference to the next node, so you have to scan from the head to find the node before it in order to unlink it.
O(1). Each node stores a reference to its previous node, so you can unlink it directly without scanning the list.
What is the space tradeoff between singly-linked and doubly-linked lists?
A doubly-linked list uses more memory, since every node stores an extra prev reference. but, it allows for O(1) removal by node reference
What is the space efficiency tradeoff between array-backed lists and linked lists?
Array-backed lists may waste space on empty, preallocated slots in the underlying array. Linked lists have no empty slots, but every element carries extra overhead for its node object and its next (and prev, for doubly-linked lists) references.
What is the time complexity for the lookup operations in an array-backed list vs a linked list? Why?
O(1) for an array-backed list and O(n) for a linked list
an array-backed list computes the position directly from the index (math); a linked list has to scan from the head.
When would a linked list be preferred over an array-backed list?
When you frequently add or remove at the front of the list (like a queue), when you remove nodes you already hold references to (doubly-linked), or when you want to avoid wasted capacity
Which abstract data types can a linked list be used to implement?
List, Queue, and Stack. With a head and tail pointer, adding at one end and removing from the other end are both O(1) (for removing from the tail, you need a doubly-linked list).
Why does the height of a binary tree matter for the complexity of its operations?
Operations like insert, remove, and contains in BSTs, heaps, and treaps all have O(height). A balanced tree has height O(log n); a completely unbalanced one has height O(n).
What is the best-case time complexity of insert, remove, and contains in a binary search tree, and why?
O(height) = O(log n). best case is when tree is balanced, so height = log n
What is the worst-case time complexity of insert, remove, and contains in a binary search tree, and why?
O(n). If the tree is skewed (elements inserted in ascending order, for example), it effectively becomes a linked list, so its O(height) = O(n)
Which abstract data types can a binary search tree be used to implement, and why?
Sets and Maps bc neither needs to preserve insetion order
How does a BST compare to an list for checking whether an element is in the collection?
A balanced BST does contains in O(log n), because each comparison eliminates about half the remaining tree. An unsorted list has to linearly check elements one by one, which is O(n).
What benefit does a BST have over a hash-based Set or Map?
BST keeps elements in strict order all the time
difference between BST with total preorder and with total order
Total order doesn’t allow duplicates
What two constraints does a binary heap add to a binary tree?
1) The shape constraint: every level is full except possibly the bottom level, and the bottom level's nodes are as far left as possible.
2) The partial ordering constraint (the heap property): for a max-heap, parent is always greater than children; for a min-heap, parent is always less than children
What is the difference between a min-heap and a max-heap?
min-heap: parent is less than or equal to its children
max-heap: parent is greater than or equal to its children
What is the time complexity of inserting and removing into a binary heap, and why?
O(log n). The swaps only happen along one branch from the bottom up toward the root (o reverse for remove), and because heaps are guaranteed to be balanced, its height is always O(log n).
What is the time complexity of contains or removing an arbitrary element from a binary heap, and why?
O(n). The heap is only partially ordered (children > or < than parent) so you can't eliminate half the tree at each step. You have to search linearly.
Which abstract data type is a binary heap a good implementation of, and why?
A priority queue, where the highest-priority element is removed next. Removing and insertion is O(log n)
What is a space advantage of storing a binary heap in an array?
Because the heap is always complete, it fits in an array with no gaps. also no need for node objects or child references. can find a node's children and parent by index arithmetic (parentIdx = childIdx / 2, where the first element in the array is null)
Which constraints does a treap enforce on its keys and its priorities?
Keys → BST constraint (left<node<right)
Priorities —> heap constraint (max-heap: parent priority >= children
What is the purpose of assigning random priorities to treap nodes, from a complexity standpoint?
Random priorities make the tree's shape the same as if the keys had been inserted into a normal BST in random order. That makes the tree very likely to be balanced (P(worst case) = 2^(n-1)/n!), so all operations are expected O(log n), even if the keys are inserted in sorted order.
Which abstract data types can a treap be used to implement?
Sets and Maps
What assumption is needed for trie operations to be considered O(1) with respect to the number of elements?
we assume that the length of the strings (m) is bounded by a constant, and the character set is fixed (26 lowercase letters), so moving from a node to the right child takes constant time, so O(m) must also be constant.
What is the time complexity of insert, contains, contains prefix, lookup, and remove on a trie, and why?
O(m), where m is the length of the input string, because each operation visits one node per character. It doesn't depend on the number of elements in the trie, so it's O(1) with respect to n (assuming string length is bounded and the alphabet is fixed).
Which abstract data types can a trie be used to implement?
Sets or Maps (with string keys/elements), since neither needs to preserve insertion order
How do compressed tries address the space disadvantage of tries?
They combine chains of nodes with only one child into a single node with multiple characters, reducing the total number of nodes.
What does Comparable's compareTo() allow you to do?
It allows internal comparisons, where the class itself defines this ordering.
When is it a better design to use the Comparable interface?
When you want to define a single default order defined for your own class, or use the order that alrdy exists
When is it a better design to use the Comparator interface?
if you need to define multiple custom orders for the same objects or you don't like the default order for that class
What are the return values for when this/o1 is less than, equal to, or greater than o/o2
< 0
= 0
> 0
How many parameters does compareTo() take vs compare(), and why?
compareTo(T o) takes one parameter because it’s called on this
compare(T o1, T o2) takes two because the Comparator is a separate object comparing two others.
Say you want to sort a list of Student objects by GPA sometimes and by last name other times. Should you use Comparable or Comparator?
Comparator, because you need multiple custom orders
Example: what does "apple".compareTo("banana") return?
A negative number; String's natural ordering is alphabetical and "apple" comes before "banana"
1) Deterministic: the same input always maps to the same hash code, or you could never find a key again.
2) Uniform distribution: keys are spread evenly across slots, even when inputs are similar, which keeps collisions (and chains) short.
3) Efficient: computing the hash is O(1), so it doesn't slow down every operation.
Sets and Maps, since neither needs to preserve insertion order