2024/05/18
Think about BFS/DGS again
- Examples
2024/05/16
Think about unionfind again
- Abstraction
- Able to take union of sets
- Able to find which set an element is in (sort of equivalently, checking if two elements are in the same set)
- Approaches
- Naive:
- a map that tracks elem -> set label
- Union of two sets A and B now takes O(min(|A|, |B|)) time (assuming you know set size for each of them, update each of the label of the smaller set). In other words, worst case O(n).
- Find which set an element is in O(1)
- Improved:
- For each set, use an element of the set as its representative.
- Property: representatives of sets are then fixed point of the elem -> set label map.
- Union of two sets A and B: only update label of the representatives. This is O(1). (only one update is needed)
- Find which set an element is in:
- would need to keep traverse the elem -> set label map until you find a fixed point, which is then the true representative.
- Don’t have a good sense what the complexity is. Not sure how many steps merging happen.
- For each set, use an element of the set as its representative.
- Trick 1
- When doing find set, you find the true representative v not just from your starting point a; you find the true representative for all nodes along the path [av].
- Doing this improves find_set to be O(log n) amortized (Not sure why; same problem why I was stuck about complexity)
- Trick 2
- When doing union set, define a metric around size of a node (e.g. size of tree with root node, depth of tree with root node), and attach node with smaller metric to node with larger metric.
- Point: resulting tree can’t be too imbalanced.
- Doing trick 1 + trick 2 – time complexity = O(inverse ackermann(n)) apparently; effectively O(1) (not sure why, but okay)
- Naive:
- Examples
- https://leetcode.com/problems/number-of-islands/
- Union find speed/memory is p25
- BFS is faster; speed/memory p90
- https://leetcode.com/problems/redundant-connection/
- https://leetcode.com/problems/validate-binary-tree-nodes
- https://leetcode.com/problems/surrounded-regions/
- Again, BFS probably faster
- https://leetcode.com/problems/minimize-hamming-distance-after-swap-operations/
- https://leetcode.com/problems/number-of-islands/
2024/05/08
Think about heap/priority queue again:
- data structure of sortable elements where
- Insert is O(log n)
- Delete is O(log n)
- Peek (smallest) is O(1)
- Pop (smallest) is O(log n)
- Heapify the entire list is O(n)
- Sample usage
- Finding k-th smallest element in a list – O(n + k log n)
- Compared to sorting: O(n log n)
- Compared to keeping a sorted list of k smallest elements: O(n log k)
- Finding k-th smallest element in a list – O(n + k log n)
- How does a heap look like
- Max heap: binary tree, where parents >= child nodes
- Heapify: greedy approach – either sift up, or sift down
- Sift down is more efficient, and sifting whole array down is O(n). (https://stackoverflow.com/questions/9755721/how-can-building-a-heap-be-on-time-complexity)
- Exercises
- https://leetcode.com/problems/kth-largest-element-in-an-array/
- https://leetcode.com/problems/ugly-number-ii/
- Not exactly priority queue, but whatever
- https://leetcode.com/problems/top-k-frequent-elements/
- Simple sorting is quick enough, but whatever
- https://leetcode.com/problems/k-th-smallest-prime-fraction
- https://leetcode.com/problems/maximum-number-of-eaten-apples/
- https://leetcode.com/problems/most-frequent-ids
- An example where I needed to manually implement heap, since python heapq doesn’t support update.
- Apparently the Python solutions there all used a hack to get around the update issue. While the logic makes sense, it’s hard to read/maintain – ignore that approach.
