Building Bridges
Sort by north (ties by south). Keep tails[k] = the smallest south end that finishes a run of k + 1 bridges. For a new bridge with south end s, find the first tail bigger than s with binary search. Replace that tail with s. If no tail is bigger than s, append s. The answer is the number of tails.
A bridge with south end s can extend a run only when the run's last south end is not higher than s, so the longest run it can extend is the one that the upper_bound search finds.
Problem
Picture a river with cities on both banks. Each city on the north bank is paired with one city on the south bank by index: north[i] can only be joined to south[i]. A bridge joins north[i] → south[i].
You want as many bridges as possible, with no two bridges crossing. Two bridges cross when one starts further left on the north bank but ends further right on the south bank. Bridges that start or end at the same x-coordinate do not cross.
Return the largest number of bridges you can build.
Two lists of the same length n: north and south. Bridge i joins north[i] to south[i].
The largest number of bridges that can be built with no crossing.
The bridges 2 → 6 and 1 → 5 do not cross, and they can be built together. No set of three bridges works without a crossing.
The bridges 1 → 2, 3 → 4, 5 → 5, 6 → 7 and 7 → 8 all go up on both banks, so none of them cross.
- • Both lists have the same length `n`. No other limits are given.
First, think yourself
Before opening any solution, try to answer these on paper. Use hints only when stuck — each hint is counted.
- 1.
Two bridges cross when their order is flipped on the two banks. Which order do I need to keep on both banks?
- 2.
If I sort the bridges by their north end, what must the south ends do so that no two bridges cross?
- 3.
Does the order of the input lists matter for the answer? What happens if I look at the south ends in the order they were given?
- 4.
Can two bridges share the same north x-coordinate? If they do, what order should their south ends be in?
- 5.
This looks like the Longest Increasing Subsequence. What changes about the word 'increasing' here?
Brute force approach
Better approach
Optimized approach
Why does this algorithm work?
Dry run
All approaches compared
| Approach | Idea | Time | Space |
|---|---|---|---|
| Brute Force | Sort by north, then try keep or skip for each bridge; keep a bridge only if its south end is not lower than the last one kept | O(2^N) | O(N) |
| Better | dp[i] = most bridges in a run that ends at bridge i; check every earlier bridge whose south end is not higher | O(N²) | O(N) |
| Optimal | Sort by north; keep tails[k] = smallest south end of a run of k + 1 bridges; binary search each new south end | O(N log N) | O(N) |
Why does this belong to this pattern?
- “cities paired by index”Each bridge is one pair (north, south). Sort the pairs as a whole. Do not sort the two lists separately.
- “no two bridges cross”After sorting by north, the south ends must never go down. That is a rule on one list, so the 2D problem becomes a 1D one.
- “maximum number of bridges”We want the longest valid run, so the answer is a length, which `tails` gives directly.
The sort turns a 2D rule into a 1D one: after sorting by north, bridges are valid exactly when their south ends never go down. Ties on north are sorted by south, so bridges that share a north end can all be kept. The key difference from Classic LIS is that equal values are allowed, so the search uses upper_bound. Best Team With No Conflicts uses the same sort-then-run idea, but adds a score to each run.
Don't make this mistake
The input order is not the order of the north ends, so a run of south values can jump across bridges that cross. On the first example the south values in input order are 2, 3, 6, 5. The run 2, 3, 6 has length 3, so this code returns 3. But the bridges 6 → 2 and 2 → 6 cross each other, so the right answer is 2.
Two bridges that start at the same north end do not cross, so both can be kept. Sorting ties with the south end descending puts the bigger south first, and the run can then keep only one of them. On north = [3, 3] and south = [7, 2] the right answer is 2, but this code returns 1.
Two bridges that end at the same south city do not cross, so the second can follow the first. On north = [1, 2] and south = [5, 5], the right answer is 2. lower_bound replaces the 5 instead of adding a new run, so it returns 1.
Want to implement this?
Write it yourself on GeeksforGeeks, then come back and compare your code with the solutions above.
Open coding workspaceHow this concept connects to System Design & C++ Systems
Top engineering interviews test whether you understand how algorithms like DP — Longest Increasing Subsequence translate into production architectures and low-level memory mechanics.
Foundations: Object-Oriented Principles in C++23
Class invariants, pure virtual interfaces, and RAII smart pointers.
Food Delivery System (Zomato Architecture)
Real-world machine coding application of algorithms and design patterns.
Pointers vs References Deep Dive
Pointer arithmetic and memory layout under the hood.
Virtual Method Table (vtable) & Memory Layout
Polymorphism, vptr overhead, and multiple inheritance in memory.