001 Notes

Ordered Optimization Professional Playbook

Overview and Reading Path

Ordered optimization is used when imposing an order makes the best next step, search boundary, or active set manageable.

The order may be:

  • sorted array order
  • smallest cost first
  • largest priority first
  • answer feasibility order
  • event time order
  • interval endpoint order
  • dynamic tree/index order

Read in this order:

  1. Identify what is ordered.
  2. Identify what can be safely discarded or selected.
  3. State the invariant.
  4. Pick the data structure that preserves the order.
  5. Verify the proof: monotonicity, greedy safety, or shortest-path relaxation.

Core Vocabulary

TermMeaning
Ordered domainThe values, positions, costs, or events arranged by order
BoundaryA point that separates possible from impossible or searched from unsearched
Feasibility predicateA yes/no check used in binary search on answer
Greedy choiceA local choice that is provably safe
Active setItems currently relevant during a sweep
PriorityThe key that decides which item is processed first
RelaxationUpdating a best-known cost through an edge or candidate

Beginner Mental Model

Think of a messy pile of tasks. If you sort or prioritize the pile correctly, you no longer need to try every order.

Examples:

cheapest path first
smallest feasible answer first
earliest ending interval first
highest frequency task first
next event in time order

Ordered optimization is the skill of finding the order that makes a decision safe.

From Brute Force To This Pattern

Brute force tries candidates without proof:

try every path
try every answer
try every interval subset
try every task order

Ordered optimization adds a proof-bearing order:

sort candidates
or prioritize by current best key
or binary search the answer boundary

The shift is from “try all” to “prove this candidate or side can be discarded.”

What Information Becomes Reusable

Reusable information is the order relation:

  • sorted positions let binary search discard half
  • monotonic feasibility lets answer search discard a range
  • heap priority makes the current best candidate available
  • sorted interval endpoints make overlap decisions local
  • active sets summarize currently relevant events
  • ranked indexes support dynamic order queries

What This Mental Model Prevents

This model prevents:

  • using binary search without a monotonic condition
  • using greedy without a safety proof
  • using BFS when weighted costs require Dijkstra
  • sorting by the wrong interval endpoint
  • keeping stale heap entries as valid answers

Small Visual Model

unordered candidates:
    ? ? ? ? ? ? ?

ordered candidates:
    impossible | unknown | feasible
                  ^
              move boundary

What This Family Is / Is Not

Use this family when sorted order, priority order, or monotonic feasibility lets you discard candidates or choose the next best item.

Do not use it when:

  • all moves have equal cost and plain BFS is enough
  • the problem only needs one linear scan summary
  • there is no monotonic predicate for the guessed answer
  • the greedy choice cannot be justified

Universal Template

choose the ordered domain
initialize boundary, heap, sorted list, or active set

while work remains:
    take the next ordered candidate
    discard impossible candidates
    update the best answer or boundary
    preserve the ordering invariant

return the final boundary or best answer

Core Mental Model

The central question is:

What order lets me ignore work without losing the optimum?

Ordered optimization is not one technique. It is a family of ways to exploit order so that a candidate can be finalized, discarded, delayed, or compared without brute force.

Every ordered optimization solution has four contracts:

ordered domain:
    values, positions, costs, times, intervals, ranks, or events

safe decision:
    the exact reason one side, candidate, or prefix can be ignored

maintained structure:
    bounds, heap, sorted list, active set, monotonic predicate, or rank index

answer meaning:
    boundary, best candidate, minimum cost, active maximum, or feasible value

How To Read This Family Visually

Use the same symbols throughout this section:

[]    active candidate range, heap item, interval, or event
{}    maintained order structure: heap, active set, bounds, ranks
^     current midpoint, popped item, event, or greedy choice
-->   discard, relax, release, or advance by order
x     proven impossible, stale, dominated, or safely ignored
==    boundary/equivalence under the ordering proof
...   candidates not inspected individually

One-minute mental model:

see an ordered domain
    -> ask what decision the order makes safe
    -> store bounds, heap, active set, or ranks
    -> discard, finalize, or advance candidates
    -> invariant: ignored candidates cannot beat the maintained answer

Read every diagram as:

shape:
    what is ordered?
memory:
    what structure preserves the useful order?
action:
    what candidate is discarded, finalized, or made active?
invariant:
    why can no skipped candidate win?

ASCII Visual Map

Ordered optimization should feel like shrinking or finalizing candidates because the order gives a proof.

binary search boundary:

index:      0   1   2   3   4   5   6
predicate:  F   F   F   T   T   T   T
                         ^
                         first true answer

The search is for the boundary, not for a lucky working sample.
Dijkstra heap finality:

heap before pop:

cost 2: A   <-- cheapest unsettled state
cost 5: B
cost 8: C

pop A:
    A is final only because all edge weights are nonnegative.
greedy interval exchange:

candidate intervals sorted by finish:

    [----A----]
       [--B--]
             [---C---]

Pick the compatible interval that finishes earliest.
It leaves the widest future suffix for the rest of the solution.
sweep line active set:

time:     1      3      5      7
events:  +A     +B     -A     -B

active after event:
         {A}   {A,B}   {B}    {}

Queries at time t read exactly the active set after all events <= t.
top-k heap:

stream:  9  1  7  3  8     k = 3

kept heap after scan:
        7
       / \
      9   8

The root is the weakest kept candidate; anything smaller cannot enter top k.

Ordered Domain

First name what is ordered. Sorting the wrong thing often creates a plausible but unprovable greedy solution.

Problem shapeOrdered thing
binary searchindex or value range
binary search on answercandidate answer value
Dijkstratentative path cost
interval greedyfinish time, start time, or event time
heap schedulingnext available time or highest priority
sweep linecoordinate-ordered events
order statisticscompressed rank or sorted key

Problem Shape Diagrams

binary search:

left                 mid                 right
 v                   v                    v
[ ? ][ ? ][ ? ][ x ][ ? ][ ? ][ ? ][ ? ]

compare at mid, then discard one side by proof.
invariant: the answer remains inside the undiscarded side
binary search on answer:

candidate answer:
1   2   3   4   5   6   7   8
F   F   F   F   T   T   T   T
                ^
              boundary

The ordered thing is the answer value itself.
invariant: feasibility is monotonic across candidate values
Dijkstra:

start --2--> A --4--> target
  |                         ^
  +----7----> B -----1------+

heap order:
cost 2: A
cost 7: B

The cheapest unsettled cost is processed first.
invariant: popped cost is final when all edges are nonnegative
interval greedy:

time:  0    2    4    6    8
       [----A----]
          [--B--]
                [--C--]

Sort by the endpoint that makes the safe local choice provable.
invariant: the chosen interval leaves an optimal-compatible future
heap scheduling:

tasks arrive:
T1 duration 4
T2 duration 2
T3 duration 3

machine heap by next free time:
time 0: M1, M2
time 2: M2
time 4: M1

The top resource is the next available one.
invariant: heap top is the resource that can be reused earliest
sweep line:

coordinate:  1      3      5      8
event:      +A     +B     -A     -B

active:
after 1: {A}
after 3: {A, B}
after 5: {B}
after 8: {}

invariant: active set contains exactly events covering this coordinate
order statistics:

values:       40   10   30   10
sorted uniq:  10   30   40
rank:          1    2    3

rank keeps order while making indexes dense.
invariant: rank comparisons match original value comparisons

The order must connect directly to the proof. Sorting intervals by start time helps merging; sorting by finish time helps maximum compatible selection.

Safe Discard or Safe Finalization

The decision is safe only when the invariant proves that ignored candidates cannot later become better.

StrategySafe decision
binary searchcomparison proves the answer is entirely on one side
binary search on answerfeasibility partitions answers into false/true
Dijkstraminimum heap pop is final under nonnegative weights
greedy intervalsearliest finishing compatible interval leaves most room
heap top-kvalues below heap root cannot enter current top k
sweep lineall earlier events have been fully applied
ordered set/rankrank query answers among currently inserted keys

If you cannot say why a candidate is safe to discard, do not code the ordered solution yet.

Monotonicity

Binary search on answer requires a monotonic predicate:

false false false true true true

or the reverse. The predicate must answer a yes/no question for one candidate value.

Examples:

CandidatePredicate
eating speedcan finish within h hours
ship capacitycan ship within d days
maximum subarray sum limitcan split into at most k groups
distance between ballscan place at least m balls
minimized maximum valuecan redistribute within this cap

The returned answer is the boundary, not the first value that happened to work in a trial loop.

Priority Finality

Heap-based optimization depends on what the top of the heap means.

push candidate with priority
pop best current candidate
if stale, skip
if finality condition holds, commit it
relax or generate neighbors

For Dijkstra, finality requires nonnegative edge weights. For top-k, the heap root is the weakest kept candidate. For scheduling, the heap root is the next resource that becomes available.

Greedy Exchange

Greedy sorting needs an exchange idea:

If an optimal solution does not use my local choice, I can swap my local choice
into it without making the solution worse.

This is why earliest-finish interval selection works and arbitrary “take the largest-looking item” often fails. The local choice must preserve the future search space or objective value.

Sweep Active Set

Sweep line problems turn geometry, intervals, or time into ordered events.

sort events
active = empty
for event in order:
    remove expired information
    add newly active information
    answer query using exactly the active set

Tie-breaking is part of the model. Whether starts happen before ends at the same coordinate changes meeting-room counts, skyline edges, and interval coverage.

Universal Ordered Template

identify ordered domain
define the safe decision invariant
choose bounds, heap, sorted events, or ordered structure

while undecided candidates remain:
    inspect the next ordered candidate
    prove which candidates are final, discarded, or still active
    update the maintained structure
    update answer boundary or best known result

return the boundary, optimum, order, or active-query result

Strategy-Specific Mental Model

StrategyMental modelFailure signal
binary searchshrink a sorted possibility rangeno sorted side or invariant
answer searchfind boundary of monotonic feasibilitypredicate flips more than once
Dijkstraexpand cheapest unsettled statenegative edge changes finality
greedy sortlocal choice can be exchanged into optimumlocal choice has no proof
heappriority exposes current best candidatestale entries not handled
sweep lineactive set reflects processed eventsevent ties are undefined
ordered rankcompressed order preserves comparisonscompression loses equality/order

Mini Traces

Trace 1: binary search on answer.

capacity candidates:
10  11  12  13  14  15
F   F   F   T   T   T

step 1:
    mid = 12, feasible = false
    discard [10, 11, 12]
    invariant: no smaller capacity can work if 12 fails

step 2:
    mid = 14, feasible = true
    keep [13, 14], discard bigger only after narrowing
    invariant: answer is still the first feasible boundary

Trace 2: Dijkstra heap.

heap:
    [2,A] [5,B] [9,C]

step 1:
    pop [2,A]
    commit dist[A] = 2
    invariant: A is final because no unsettled path can be cheaper

step 2:
    relax A -> D with +3
    push [5,D]
    invariant: heap contains known unsettled candidates ordered by distance

Contrast Diagrams

BFS vs Dijkstra:

BFS:
    queue by layers
    distance 0 -> distance 1 -> distance 2
    invariant: every edge has equal cost

Dijkstra:
    heap by total cost
    cost 2 -> cost 5 -> cost 6
    invariant: cheapest unsettled state is final with nonnegative weights

Binary search vs two pointers:

binary search:
    [possible answer space]
          ^
        mid test
    invariant: predicate/order discards half the answer space

two pointers:
    left -->             <-- right
    invariant: pointer movement discards impossible pairs in one scan

Misclassification Checks

Use this family when order proves work can be skipped. Be careful when:

SymptomBetter family may be
choices repeat and need memoizationState Space Exploration
only adjacent scan facts matterSequential Aggregation
many persistent range updates/queries dominateRange Query & Indexed Aggregation
edges and reachability dominateConnectivity Discovery
numeric identities replace the searchMathematical Numeric Reasoning

The clean test is: can you point to the exact ordering proof that makes ignored candidates irrelevant? If not, the pattern choice is not ready.

Detailed Translation Workflow

Translate every ordered optimization problem in this order:

1. What is ordered: input, answer, cost, time, interval, or rank?
2. What decision does that order make safe?
3. What invariant proves discarded candidates cannot win?
4. What structure preserves the order while the scan/search changes?
5. What is returned: boundary, best candidate, shortest cost, or active maximum?

If step 2 has no proof, the pattern choice is not ready.

Strategy Map

StrategyOrdered thingMain invariant
Dijkstra / heap shortest pathtentative distancepopped state is final
Binary searchsorted positionstarget side can be discarded
Binary search on answeranswer valuefeasibility is monotonic
Greedy + sortingcandidateslocal safe choice remains globally valid
Heap / priority queueactive candidatestop is current best
Sweep lineeventsactive set reflects processed events
Ordered structuresindexes or ranksprefix/range/order queries stay current

Problem Translation Table

Problem typeState / summaryOrdered decisionEngine
Search Insert Positionleft, rightdiscard half by mid comparisonbinary search
Find Minimum in Rotated Sorted Arrayboundsdetect sorted halfbinary search
Search 2D Matrixflattened index rangecompare middle cellbinary search
Koko Eating Bananasspeed guessfeasible speed monotonicbinary search on answer
Split Array Largest Summax-subarray-sum guesscan split into <= k partsbinary search on answer
Capacity to Ship Packagescapacity guesscan ship within daysbinary search on answer
Swim in Rising Watermin reachable timepop lowest water-level stateDijkstra / heap
Network Delay Timeshortest time to noderelax smallest tentative distanceDijkstra
Path With Minimum Efforteffortexpand smallest effort pathDijkstra or binary search
Kth Largest Elementheap or partitionkeep top k / partition around pivotheap or quickselect
Top K Frequent Elementsfrequency heappop highest frequencyheap
Meeting Rooms IIsorted starts/ends or min-heapexpire earliest ending meetingsweep or heap
Merge Intervalssorted startsmerge with previous active intervalgreedy sorting
Non-overlapping Intervalssorted by endkeep earliest finishing intervalgreedy
Minimum Arrows to Burst Balloonssorted by endshoot at earliest ending balloongreedy intervals
Task Schedulerremaining countsrun highest remaining valid taskheap
Count of Smaller Numbers After Selfrank-compressed valuesquery prior/later ranksFenwick / ordered structure
My Calendarsorted intervalsdetect neighbor overlapordered map/list

Canonical Examples

Dijkstra: Cheapest State First

Invariant:

When a state is popped from the heap with its best known distance, that
distance is final if all edges are non-negative.

Skeleton:

import heapq


def dijkstra(graph, start):
    dist = {start: 0}
    heap = [(0, start)]

    while heap:
        cost, node = heapq.heappop(heap)
        if cost != dist[node]:
            continue

        for nei, weight in graph[node]:
            next_cost = cost + weight
            if next_cost < dist.get(nei, float("inf")):
                dist[nei] = next_cost
                heapq.heappush(heap, (next_cost, nei))

    return dist

Binary Search: Search Insert Position

Invariant:

The answer is always inside [left, right].
def search_insert(nums, target):
    left = 0
    right = len(nums)

    while left < right:
        mid = (left + right) // 2
        if nums[mid] < target:
            left = mid + 1
        else:
            right = mid

    return left

Binary Search on Answer: Split Array Largest Sum

Invariant:

If max_sum works, any larger max_sum also works.
def split_array(nums, k):
    def feasible(limit):
        groups = 1
        current = 0
        for value in nums:
            if current + value > limit:
                groups += 1
                current = 0
            current += value
        return groups <= k

    left = max(nums)
    right = sum(nums)

    while left < right:
        mid = (left + right) // 2
        if feasible(mid):
            right = mid
        else:
            left = mid + 1

    return left

Greedy Intervals: Minimum Arrows

Invariant:

Shooting at the earliest ending balloon preserves the most room for future
balloons.
def find_min_arrow_shots(points):
    points.sort(key=lambda x: x[1])
    arrows = 0
    arrow_end = None

    for start, end in points:
        if arrow_end is None or start > arrow_end:
            arrows += 1
            arrow_end = end

    return arrows

Heap: Top K Frequent

Invariant:

The heap stores the current k strongest candidates by frequency.
from collections import Counter
import heapq


def top_k_frequent(nums, k):
    heap = []
    for value, freq in Counter(nums).items():
        heapq.heappush(heap, (freq, value))
        if len(heap) > k:
            heapq.heappop(heap)
    return [value for freq, value in heap]

Decision Rules

Use normal binary search when the input itself is ordered. Use binary search on answer when the answer range is ordered and feasibility is monotonic. Use Dijkstra when paths have non-negative, unequal costs. Use greedy sorting when a sorted local choice can be proven safe. Use a heap when the best active candidate changes over time. Use sweep line when interval/event order reveals active state. Use Fenwick/segment trees when dynamic ordered prefix or rank queries are needed.

Common Failure Modes

  • Using BFS for weighted edges.
  • Binary-searching a predicate that is not monotonic.
  • Returning mid instead of the converged boundary.
  • Sorting intervals by the wrong endpoint for the greedy proof.
  • Forgetting stale-entry checks in Dijkstra heaps.
  • Using a heap when a sorted one-pass scan is enough.
  • Losing duplicate/rank information in ordered structure problems.

Performance Notes

Binary search is usually O(log n) over positions or O(check * log range) over answers. Heap algorithms are usually O((n + edges) log n) or O(n log k). Sweep line is usually dominated by sorting: O(n log n). Fenwick and segment trees trade more implementation complexity for O(log n) updates and queries.

Cheat Sheet

Binary search:
    What half can I discard?

Binary search on answer:
    What predicate changes from false to true?

Dijkstra:
    What is the distance label?
    Are all edges non-negative?

Greedy:
    What local choice is safe, and why?

Heap:
    What does the top mean right now?

Sweep:
    What happens at each event?

Ordered structure:
    What rank/range query must stay dynamic?

Extended Translation Notes

Ordered optimization problems should be translated through the order first.

Step 1: Identify the Ordered Domain

Ask what can be sorted, prioritized, or searched.

SurfaceOrdered domain
sorted arrayindex positions
answer rangepossible answer values
weighted graphtentative path costs
intervalsstarts, ends, or event times
tasksdeadlines, profits, frequencies
dynamic rankscompressed values

If no order is useful, this family is probably not the right first choice.

Step 2: Identify the Safe Discard or Safe Choice

Ordered optimization needs a proof.

Examples:

Binary search:
    one side cannot contain the answer

Binary search on answer:
    feasibility is monotonic

Dijkstra:
    the cheapest popped state is final

Greedy intervals:
    earliest finishing interval leaves maximum future room

Heap:
    the top element is the best active candidate right now

Step 3: Pick the Data Structure

NeedStructure
discard halfbinary search indexes
repeated current min/maxheap
active intervals by timesorted events plus heap/map
dynamic prefix/rank queryFenwick or segment tree
sorted neighbor lookupbalanced tree or sorted list
monotonic answer feasibilitybinary search on answer

Step 4: Define the Invariant

The invariant should explain why the order is trustworthy.

Good examples:

All values below left are impossible.
All values at least right are feasible.
The heap top is the smallest unsettled distance.
The active set contains exactly intervals whose start has passed and end has not.

Strategy Invariants

Dijkstra / Shortest Path With Heap

Dijkstra is ordered state exploration by cost.

Invariant:

When a state is popped with its current best distance, no undiscovered path can
reach it cheaper.

Requirements:

  • edge costs are non-negative
  • stale heap entries are ignored
  • relaxation only updates when the new distance is better

Binary search maintains a boundary.

Lower-bound form:

left is the first unknown candidate
right is one past the last unknown candidate

At the end, left == right is the insertion point or first satisfying index.

Binary Search on Answer

The answer range is ordered even if the input is not.

Predicate shape:

False False False True True True

or:

True True True False False False

Decide which boundary you want before writing the loop.

Greedy + Sorting

Greedy is not “take what looks good.” It needs an exchange argument.

Common safe orders:

Problem shapeSort by
choose max non-overlapping intervalsend time
merge intervalsstart time
assign cookiessize or greed
schedule by deadlinedeadline
minimize arrowsballoon end

Sweep Line

Sweep line converts intervals into ordered events.

Invariant:

After processing events at coordinate x, the active structure represents all
objects alive at x.

Tie-breaking matters. For example, whether an end event happens before a start event depends on whether intervals are open or closed.

Worked Problem Snapshots

Koko Eating Bananas

Ordered domain:

eating speed

Predicate:

can finish within h hours

Invariant:

If speed s works, every speed greater than s also works.

Engine:

binary search on answer

Capacity to Ship Packages

Ordered domain:

ship capacity

Predicate:

can ship all packages within D days

Bounds:

left = max(package)
right = sum(packages)

Trap:

Capacity below the largest package is impossible.

Find Minimum in Rotated Sorted Array

Ordered domain:

rotated sorted index range

Decision:

compare nums[mid] with nums[right]

Invariant:

The minimum remains inside [left, right].

Network Delay Time

Ordered domain:

shortest known arrival time

State:

node, distance

Invariant:

The first finalized distance for a node is shortest.

Trap:

Plain BFS is wrong when edge times differ.

Meeting Rooms II

Ordered domain:

meeting start times and active end times

State:

min-heap of ending times for active rooms

Invariant:

Before adding a meeting, all rooms whose end time is <= start are reusable.

Merge Intervals

Ordered domain:

interval start time

Invariant:

The output list is merged and sorted for all intervals processed so far.

Trap:

Sort by start, not end.

Non-overlapping Intervals

Ordered domain:

interval end time

Greedy proof:

Keeping the earliest ending interval leaves the most room for future intervals.

Task Scheduler

Ordered domain:

remaining task frequency and cooldown time

State:

max-heap for available tasks
queue for cooling tasks

Invariant:

Only tasks whose cooldown expired can be reinserted into the heap.

Count Smaller After Self

Ordered domain:

compressed value ranks

State:

Fenwick counts of values already seen to the right

Invariant:

Before processing nums[i], the tree contains exactly nums[i+1:].

Dry Runs

Input:

nums = [1, 3, 5, 7]
target = 6

Process:

left=0 right=4
mid=2 nums[2]=5 < 6 -> left=3
mid=3 nums[3]=7 >= 6 -> right=3
left=3 right=3 stop

Answer:

3

Dry Run: Binary Search on Answer

Input:

nums = [7, 2, 5, 10, 8]
k = 2

Bounds:

left = 10
right = 32

Feasibility examples:

limit 21 works: [7,2,5] [10,8]
limit 15 fails: [7,2,5] [10] [8]

The search converges to 18.

Dry Run: Dijkstra

Graph:

A -> B cost 4
A -> C cost 1
C -> B cost 2

Process:

pop A dist 0
    relax B = 4
    relax C = 1
pop C dist 1
    relax B = 3
pop B dist 3

The stale heap entry (4, B) is ignored later.

Dry Run: Sweep Line

Intervals:

[1, 4], [2, 5], [7, 9]

Events:

1 start -> active 1
2 start -> active 2
4 end   -> active 1
5 end   -> active 0
7 start -> active 1
9 end   -> active 0

Maximum overlap:

2