Ran Wei/CS Series/08
中文
Computer Science Fundamentals — Ran Wei

Module 08: Algorithm design

Choose between divide and conquer, greedy choices, backtracking and dynamic programming. Justify optimality instead of trusting plausible choices.

≈ 5 hours4 sessions2 labs8 exercises6 quiz questions

By the end you can

  • Recognise divide-and-conquer recurrences.
  • Construct a greedy exchange argument.
  • Explore and prune search trees.
  • Define DP state and transitions.
  • Reconstruct and check solutions.

Before you start

Recommended modules: 05, 07.

Know recursion and asymptotic bounds. The labs solve small scheduling and optimisation problems.

Contents

Study plan

5 hours

Four 75-minute sessions including practice. Allow longer for extensions or unfamiliar prerequisites. Progress is saved locally and shared between language editions.

Session 175 min
Concepts and worked examples
Session 375 min
Apply and extend
1

Divide and conquer

Divide a problem into smaller instances, solve them, then combine. Merge sort satisfies T(n)=2T(n/2)+Θ(n) for balanced splits: each level does linear merge work and there are logarithmically many levels. Binary search solves only one half, so its recurrence is T(n)=T(n/2)+Θ(1). The number of subproblems and combine cost matter; saying 'uses recursion' alone does not identify a growth rate.

Check your understanding

Why are merge sort and binary search different costs?

Worked solution

Merge sort solves both halves and merges; binary search keeps only one half.

2

Greedy choices and exchange arguments

A greedy algorithm commits to a locally attractive choice. For maximum-count nonoverlapping intervals, choose earliest finish, then repeat on compatible intervals. An optimal schedule's first interval can be replaced by the earliest-finishing one without delaying any remaining start; this exchange leaves the count unchanged and reduces to the same residual problem. Earliest start lacks that argument: one long early interval can block many short ones. Maximising total interval value is a different problem and generally needs more than this rule.

Check your understanding

Does earliest finish solve weighted interval scheduling?

Worked solution

Not generally; maximising value differs from maximising count.

3

Backtracking and exhaustive search

Backtracking extends a partial solution, rejects impossible branches and undoes a choice before trying alternatives. For subsets of n items, there are 2^n choices before pruning. A constraint can reduce actual exploration without changing the worst-case exponential bound. Exhaustive search is useful as a small-instance oracle: compare a fast algorithm's answer with all feasible possibilities. Pruning must be justified; rejecting a merely unattractive partial choice can lose the optimum.

Check your understanding

Why keep exhaustive verification inputs small?

Worked solution

The number of subsets grows exponentially.

4

Dynamic programming states

Dynamic programming reuses overlapping subproblem answers. For minimum coin count, define best[v] as the minimum count for amount v. Base best[0]=0; impossible states are infinity. Transition best[v]=min(best[v−c]+1) over positive coins c≤v. Compute increasing v so dependencies are ready. With k coin types and target A, time is O(kA), storage O(A). This is pseudo-polynomial in numeric A, not polynomial in the bit length of A. Greedy largest-coin-first fails for [1,3,4] at six: 4+1+1 loses to 3+3.

Check your understanding

Why must coin values be positive?

Worked solution

Transitions must move to smaller states; zero or negative values break that dependency order.

5

Reconstruction and independent checks

An optimum value alone may not tell the user what to do. Store the chosen predecessor at each improved state, then walk backwards to reconstruct decisions. Check feasibility independently: coin totals must equal the amount; intervals must not overlap. For a small case, compare optimality with exhaustive enumeration. This distinguishes implementation defects from a wrong recurrence. Specify unreachable and empty outcomes explicitly: amount zero has an empty valid solution, while an impossible positive amount has no solution.

Check your understanding

Are [] and None interchangeable DP results?

Worked solution

No. [] is a valid zero-amount solution; None means impossible.

6

Common misconceptions

  • Greedy correctness is specific to the objective and assumptions.
  • A DP table needs a state meaning and a valid dependency order.
7

Lab setup

Download each script and run it in a terminal with Python 3.11 or later: python m08_greedy.py. On Windows, py -3 is an alternative; on some systems use python3. The labs use only the standard library. Predict the result before running, then complete the variations. Run without -O so assertions remain enabled. Outputs below were captured by the builder. Code and output are identical in both language editions.

8

Lab 1 — Schedule intervals

Maximise the count of compatible half-open intervals. Adjacent endpoints may touch. Exhaustive search checks this small instance.

Download m08_greedy.py

"""Earliest-finish interval scheduling, checked against exhaustive search."""
from itertools import combinations
def compatible(intervals):
    ordered = sorted(intervals)
    return all(a[1] <= b[0] for a, b in zip(ordered, ordered[1:]))
def schedule(intervals):
    result, end = [], float("-inf")
    for start, finish in sorted(intervals, key=lambda item: item[1]):
        if start >= finish:
            raise ValueError("nonempty intervals required")
        if start >= end:
            result.append((start, finish)); end = finish
    return result

jobs = [(0, 4), (1, 2), (2, 3), (3, 5), (4, 6)]
chosen = schedule(jobs)
optimal = max(len(subset) for size in range(len(jobs)+1) for subset in combinations(jobs, size) if compatible(subset))
print("chosen:", chosen, "optimal count:", optimal)
assert len(chosen) == optimal == 3
assert schedule([]) == []
Captured output
chosen: [(1, 2), (2, 3), (3, 5)] optimal count: 3
  1. Choose earliest start instead and construct a failure.
  2. Add a zero-duration job and explain rejection.
  3. Attach values to jobs and explain why the oracle must change.
Worked solution

[0,10] blocks [1,2],[2,3],[3,4] under earliest start. The lab requires start<finish, so zero duration is invalid. With values, maximise summed values instead of subset length and use a weighted algorithm.

9

Lab 2 — Minimum coins

Inspect every state for amount six and reconstruct the selected coins. Infinity marks unreachable states.

Download m08_dynamic.py

"""Minimum coin count with reconstruction; impossible values return None."""
def min_coins(coins, amount):
    if amount < 0 or any(c <= 0 for c in coins):
        raise ValueError("nonnegative amount and positive coins required")
    best, previous = [0] + [float("inf")] * amount, [None] * (amount + 1)
    for value in range(1, amount + 1):
        for coin in coins:
            if coin <= value and best[value - coin] + 1 < best[value]:
                best[value] = best[value - coin] + 1; previous[value] = coin
    if best[amount] == float("inf"):
        return None
    selected = []
    while amount:
        coin = previous[amount]
        selected.append(coin); amount -= coin
    return selected

for coins, amount in [([1, 3, 4], 6), ([2, 4], 3), ([1, 3, 4], 0)]:
    result = min_coins(coins, amount)
    print(coins, amount, "->", result)
    if result is not None: assert sum(result) == amount
assert min_coins([1, 3, 4], 6) == [3, 3]
assert min_coins([2, 4], 3) is None
Captured output
[1, 3, 4] 6 -> [3, 3]
[2, 4] 3 -> None
[1, 3, 4] 0 -> []
  1. Try [2,5] at amounts 1 and 7.
  2. Compare greedy with DP for [1,3,4].
  3. Add a count-only version and compare memory responsibilities.
Worked solution

One is unreachable; seven uses 2 and 5. Six under [1,3,4] needs two coins, not the greedy three. A count-only version still stores best states but can omit reconstruction predecessors.

10

Exercises with worked solutions

Try before opening the solution. ★ applies an idea; ★★ combines ideas; ★★★ asks for design or proof.

Exercise 1 — Strategy★

Which strategy solves both halves then combines?

Worked solution

Divide and conquer.

Exercise 2 — Coin counterexample★

Compare greedy and optimum for coins 1,3,4 and amount 6.

Worked solution

Greedy: 4+1+1, three. Optimum: 3+3, two.

Exercise 3 — State table★★

Give best[0…4] for coins 1,3,4.

Worked solution

[0,1,2,1,1]. Each value uses ready smaller states.

Exercise 4 — Compatibility★★

Can [1,3) and [3,5) both be selected?

Worked solution

Yes; half-open intervals do not overlap at the shared endpoint.

Exercise 5 — Subset growth★★

How many subsets for 20 jobs?

Worked solution

2^20=1,048,576, illustrating why exhaustive verification needs small n.

Exercise 6 — Exchange argument★★★

Explain why earliest finish can replace an optimal first interval.

Worked solution

It finishes no later, so every later interval still starts after its end. The count is preserved, and the residual scheduling problem has the same form.

Exercise 7 — DP proof★★★

Why does the coin recurrence consider every optimal solution?

Worked solution

Any nonzero solution has a last coin c. Removing it leaves amount v−c; an optimal solution must use an optimal residual or replacing that residual would improve the whole. Minimise across all c.

Exercise 8 — Numeric versus encoded size★★

Why is O(A) not polynomial in log₂ A?

Worked solution

Writing A needs about log₂ A bits; A grows exponentially in that bit count. State whether size means value or encoded length.

11

Self-check quiz

Choose an answer for feedback; reset to retry. A text answer key is available without JavaScript.

1

A greedy choice needs?

2

Interval maximum-count rule?

3

DP reuses?

4

best[0] for coin count?

5

Backtracking worst-case subsets?

6

Reconstruction stores?

Answer key
  1. A — Local attractiveness alone is insufficient.
  2. B — An exchange preserves future feasibility.
  3. C — Memoisation or tables avoid repeated work.
  4. A — No coins make zero.
  5. B — Each item can be included or excluded.
  6. C — The value alone may not identify decisions.
12

Guided reading

13

Review and the next step

For a new optimisation task, define its objective, feasible solutions and state before choosing a strategy. Module 09 investigates the machine that executes these procedures.

14

Key terms

TermMeaning
Optimal substructureAn optimum can be assembled from appropriately optimal subproblems.
BacktrackingExplore choices, reject infeasible branches and undo choices.
Exchange argumentReplace an optimal choice without worsening the objective.