Lab: sorting problems
Three problems where sorting or binary search is the decisive move — meeting rooms, bisect insertion, and minimum ship capacity.
- Solve a scheduling problem by sorting intervals and scanning for overlaps
- Use bisect_left to find a target's insertion position in O(log n)
- Apply binary search on a value range to find minimum ship capacity
This is an optional lab. Three problems — each one has a naive O(n²) or brute-force solution, but sorting or binary search reduces it to O(n log n) or better. Work through the starter code, then check your solution below.
Problem 1 — Meeting rooms
Can a person attend all meetings in a schedule? Each meeting is an interval
[start, end]. Two meetings conflict if one starts before the other has ended.
The key move: sort by start time. After sorting, any overlap must occur between adjacent intervals — you only need one pass to find it. Without sorting you would need to compare every pair: O(n²).
Implement meeting_rooms(intervals) that returns True if a person can attend all meetings (no overlaps), False otherwise. Intervals are [start, end] pairs. Sort by start time, then check adjacent pairs.
meeting_rooms([[0,30],[5,10],[15,20]]) → Falsemeeting_rooms([[5,8],[9,15]]) → TrueAfter sorting, why is checking only adjacent pairs enough? Because if meeting A ends after meeting C starts, and B is between them in sorted order, then B starts after A starts. If A overlaps C, A must also overlap B (or B overlaps C) — the overlap cannot "skip" a sorted neighbour. One linear scan is sufficient.
Problem 2 — Search insert position
Given a sorted list of distinct integers and a target, return the index where
the target is found, or the index where it would be inserted to keep the list
sorted. This is precisely what bisect_left computes.
The key move: bisect_left runs in O(log n) by binary search. A linear
scan would be O(n) — fine for small lists, but the point is to recognise when
a sorted structure enables a logarithmic lookup.
Implement search_insert(nums, target) returning the index where target appears or would be inserted in the sorted list nums. Use bisect_left.
search_insert([1,3,5,6], 5) → 2search_insert([1,3,5,6], 2) → 1search_insert([1,3,5,6], 7) → 4bisect_left finds the leftmost index where the list can accept target
without violating sorted order. If target is already in the list, it returns
its index. If not, it returns the position just before the first element that
exceeds target. This is a direct application of the binary-search-on-value
pattern from the previous lesson.
Problem 3 — Minimum ship capacity
A conveyor belt has packages with weights weights[0..n-1] (loaded in order).
Find the minimum ship capacity that ships all packages in at most days days.
Packages must be loaded in the given order — you cannot reorder them.
The key move: binary search on the answer. The search space is the capacity
value: at minimum the ship must hold the heaviest single package (max(weights)),
and at maximum it can hold all packages in one day (sum(weights)). For any
candidate capacity c, you can test in O(n) whether it is sufficient by
simulating greedy loading. The feasibility condition is monotone: if c works,
c + 1 also works. Binary search finds the minimum valid c in O(n log(sum)).
This is the "binary search on the answer" pattern introduced in binary search variations. The pattern appears whenever: (1) the answer is an integer in a known range, and (2) testing any candidate answer takes polynomial time and the condition is monotone.
Implement minimum_capacity(weights, days) returning the minimum ship capacity to ship all packages in at most days days, loading in order. Binary search between max(weights) and sum(weights).
minimum_capacity([1,2,3,4,5,6,7,8,9,10], 5) → 15minimum_capacity([3,2,2,4,1,4], 3) → 6The can_ship helper simulates greedy loading in O(n): keep adding packages to
the current day until the next package would exceed the capacity, then start a
new day. The outer binary search calls can_ship at most O(log(sum − max))
times, giving O(n log(sum)) total.
Done?
Three problems, one recurring theme: the naive approach iterates over all possibilities, but structure — sorted order, a sorted array's bisect points, a monotone feasibility condition — lets you discard half the search space at each step. Meeting rooms: sorting collapses an O(n²) comparison to O(n). Bisect insertion: the sorted precondition makes a single O(log n) call exact. Minimum capacity: framing the search space as a value range and the condition as a yes/no test unlocks O(n log n) over O(n × range) brute force.
Binary search variations
Understand bisect_left and bisect_right, and see how binary search generalises to any monotone function — not just sorted arrays.
Graph representation
Represent graphs as adjacency lists and adjacency matrices, compare their space and time tradeoffs, and distinguish directed, undirected, and weighted graphs.