In the coin change problem, take denominations and target amount . The natural greedy algorithm repeatedly chooses the largest denomination not exceeding the remaining amount. It chooses , then , then , for three coins. Yet uses only two.
Two is optimal: one coin cannot make because denomination is absent, and the displayed pair attains the lower bound. Therefore
The locally largest first coin loses the possibility of using the better pair of threes. This supplies a concrete failure of the greedy-choice property; optimal substructure alone does not justify the greedy choice. The dynamic programming recurrence from part (b) would compare all feasible first or last denominations and find the pair.
Both divide-and-conquer algorithms and dynamic programming derive answers from smaller problems. A typical divide-and-conquer algorithm, such as merge sort, splits an instance into separate parts and combines their answers. Dynamic programming additionally identifies repeated states across different decompositions and reuses their answers; matrix-chain multiplication is a standard example.
Thus a recursion tree may repeatedly solve the same state, whereas a dynamic programming table or memoization stores it once. The resulting recurrence and dependency order determine the running time. The principle of optimality supports combining optimal state answers; it does not by itself justify a greedy algorithm.
A greedy algorithm commits to a locally best available choice and then continues on the remaining problem without revising earlier choices. Correctness requires proving that such choices can belong to an optimal solution; local attractiveness alone is insufficient.
Kruskal's algorithm processes the edges of an undirected weighted graph in nondecreasing weight order. It accepts the next edge exactly when its endpoints lie in different components of the currently chosen forest, thereby preserving the absence of a cycle. This is greedy because it always chooses a cheapest available edge compatible with the forest constraint and never retracts an accepted edge.
The Kruskal safe edge argument explains why the choice works: if a minimum spanning tree extending the current forest lacks the chosen edge, adding that edge creates a cycle; an edge on that cycle crossing the same component boundary can be removed without decreasing connectivity. Such a crossing edge cannot be lighter than the chosen eligible edge, so the exchange does not increase total weight. The new minimum spanning tree includes the greedy choice. For a disconnected graph the same construction yields a minimum spanning forest rather than a single spanning tree.
The greedy algorithm repeatedly takes the largest denomination no greater than the remaining postage. For denominations and target , it returns , using three stamps. The optimum is , using two. Thus local preference for the largest stamp does not generally solve the coin change problem optimally.
Store a second array weight with weight[k] = 2^k. Descending through the binary digits of the answer gives this greedy algorithm:
PROCEDURE FastLog(b, n: INTEGER): INTEGER;
VAR b2, weight: ARRAY enough OF INTEGER;
    top, k, i, p: INTEGER;
BEGIN
  b2[0] := b; weight[0] := 1; top := 0;
  WHILE b2[top]*b2[top] <= n DO
    b2[top+1] := b2[top]*b2[top];
    weight[top+1] := weight[top]+weight[top];
    top := top+1
  END;
  i := 0; p := 1; k := top;
  WHILE k >= 0 DO
    IF p*b2[k] <= n THEN
      p := p*b2[k]; i := i+weight[k]
    END;
    k := k-1
  END;
  RETURN i
END FastLog;
For the second loop, write . Immediately before processing , its loop invariant is
Initially the failed squaring guard gives ; this also holds when , since then . The test succeeds exactly when . If successful, adding selects that binary digit; otherwise the upper bound tightens to . Either way the invariant holds for the next smaller . At , , so i = L.
There are squarings and descending tests. For fixed , this is arithmetic operations, hence logarithmic in the bit length of , and also within the weaker bound. This counts arithmetic operations on integers as unit cost; bit complexity would also charge for the growing operands. No division is used.
It is a greedy algorithm because it commits at every step to the cheapest remaining edge that can be added without creating a graph cycle, without revising earlier choices. The minimum spanning tree cut property explains why these locally cheapest admissible choices can be extended to an optimal spanning tree.
Dynamic programming defines subproblem optima and combines their stored answers through a recurrence. It is useful when optimal substructure and overlapping subproblems allow repeated work to be shared. Several alternative choices can be compared before an optimum is selected.
A greedy algorithm instead commits to a locally selected choice and does not later reconsider it. To be correct, its choice needs a justification such as an exchange argument or a safe-cut property, beyond merely having optimal substructure. Neither method is automatically applicable to every optimization problem. Prim's algorithm illustrates a justified greedy choice; the maximum-segment recurrence below illustrates dynamic programming.
For , use largest-denomination-first greedy algorithm steps: for , take coins and replace the residual amount by . A target is representable exactly when it is divisible by , because the smallest denomination is , not one.
To prove optimality whenever the target is representable, observe that an optimum can have fewer than coins of every denomination with : replacing such coins by one coin preserves value and reduces the count by . After all such carrying, the coefficients of are the unique base- digits of , while the coefficient of is the remaining quotient. Largest-first division produces exactly these coefficients. The greedy coin count is optimal, and can be computed with quotient/remainder operations without listing every coin.
For , distinct denominations permit only ; then all coins have value one and the answer is . This handles the printed positive-integer condition without silently assuming .
During the computation in part i, record an index attaining the minimum at every positive amount. Starting with , print and replace by , continuing until .
Every step decreases the amount and reduces the table entry by exactly one. The printed denominations therefore sum to and their number is exactly , proving optimality. The total running time is , including the output; because denomination is available. The predecessor array adds to the space complexity. This is reconstruction from the dynamic programming certificate, not the largest-denomination greedy algorithm, which need not be optimal for arbitrary denominations.
Maintain an accumulated array of denominators and an exact remaining fraction. The usual greedy algorithm can require a denominator larger than Int.MaxValue, even for an input with Int components. The following implementation uses arbitrary-precision integers internally. If that representational limit is reached, it returns the always-valid alternative consisting of num copies of . Repeated denominators are permitted by the given Egyptian fraction representation.
def fromRat(num: Int, den: Int): Array[Int] = {
  require(0 <= num && num < den)
  val start = Reduce(num, den)
  var n = BigInt(start._1)
  var d = BigInt(start._2)
  var e = Array.empty[Int]
  while (n > 0) {
    val q = (d + n - 1) / n
    if (!q.isValidInt) return Array.fill(num)(den)
    e = e :+ q.toInt
    val nextN = n * q - d
    val nextD = d * q
    val g = nextN.gcd(nextD)
    n = nextN / g
    d = nextD / g
  }
  e
}
The loop invariant is , , all entries of e are positive, and
Appending and replacing the residual by preserves this equality; division by the greatest common divisor preserves the residual's value. The loop variant is , by the proof in part (b). If nextN is zero, its greatest common divisor with nextD is nextD, giving residual . On normal exit the residual is zero and the returned array has exactly the required value. On the early-return branch, num copies of have that same value directly; the partial greedy Egyptian fraction expansion is discarded. num=0 returns an empty array.
The fallback is a correctness provision for the fixed result type, not an efficiency claim: a large repeated-term array can be impractical. An array of arbitrary-precision integers would retain the greedy Egyptian fraction expansion without this fallback. Allocation, as with any output-producing program, requires enough available memory. The BigInt remainder, greatest common divisor and checked conversion operations are documented in [ref].
Take
Its longest strictly increasing subsequences have length two. A subsequence starting with can continue with or with , but cannot use both in increasing order; one starting at has only after it.
The specified greedy algorithm may choose the longest increasing subsequence . The remaining sequence is , which needs two singleton increasing subsequences. The algorithm then uses three subsequences in total.
However, and partition the original sequence into two increasing subsequences. One is impossible because the original sequence is not increasing. Hence two is optimal and the greedy choice is suboptimal. This establishes the counterexample to removing a longest increasing subsequence without relying on a tie-breaking rule: the problem asks for a longest choice that can fail.
A perfect elimination ordering of a finite simple graph is a permutation of its vertices such that each set of later graph neighbours
is a clique. Thus is a simplicial vertex in the remaining induced subgraph . Empty and one-vertex sets satisfy the clique condition automatically. The order here is the order of deletion: goes first.
The characterization is powerful: a finite simple graph is a chordal graph if and only if it has a perfect elimination ordering. For one proof outline, the earliest vertex of an induced cycle of length at least four would have two later graph neighbours on that graph cycle that are not adjacent, contradicting the clique condition. Conversely, every nonempty chordal graph has a simplicial vertex, and every induced subgraph of a chordal graph is a chordal graph; repeatedly deleting such a vertex supplies the ordering.[ref]
In the square-plus-diagonal chordal graph above, is a perfect elimination ordering, with later graph neighbourhoods , , , and . Starting instead with fails: its graph neighbours do not form a clique, because is absent. Thus even a chordal graph can have a poor elimination ordering.
For a larger example, join three triangles along shared edges, using
The exact graph neighbourhoods are , , , , and . The ordering has later graph neighbourhoods , , , , and , all cliques; this certifies that the graph is a chordal graph without enumerating its graph cycles. Its maximal cliques , , form a junction tree in that order, with intersections and .
Figure 1.
A perfect elimination ordering removes three overlapping triangles without fill-in; choosing the central vertex first adds three edges
. Details.
To find an ordering, maximum cardinality search starts with all scores zero, repeatedly selects an unselected vertex of largest score, and increases each unselected graph neighbour's score by one. Reverse the selection order to obtain a candidate perfect elimination ordering. For the three-triangle graph, one valid selection sequence is , with scores at selection ; reversing it gives the displayed deletion order. On a chordal graph every tie choice works. On an arbitrary graph, test the resulting later graph neighbourhoods for the clique condition to recognize chordal graphs. Suitable adjacency lists, score buckets and a linear-time verification method give recognition.[ref]
The deletion rule also explains sparse Gaussian elimination. For a symmetric positive-definite matrix whose matrix graph is , eliminating pivot applies the Schur complement update
Only pairs of remaining graph neighbours of can acquire new off-diagonal entries. A perfect elimination ordering already has all those edges, so Cholesky decomposition creates no symbolic fill-in. Positive definiteness ensures nonzero pivots in exact arithmetic. Special numerical cancellation can suppress predicted entries, and floating-point rounding affects their values.[ref] In the three-triangle graph, deleting first instead connects every pair in and adds exactly . The graph was already a chordal graph; the extra fill-in comes from the ordering.
One further reward is optimal graph coloring. Process a perfect elimination ordering backwards and give each vertex the smallest positive color absent from its already colored graph neighbours. Those graph neighbours form a clique, so this greedy algorithm uses at most the clique number colors; any clique of that size requires at least that many. In the three-triangle graph, coloring gives colors , so both the chromatic number and the clique number are three. Every maximal clique also occurs among : take its earliest vertex and use maximality. The same ordering therefore supports graph coloring, maximal clique extraction and sparse computation.
Historically, Donald J. Rose, Robert E. Tarjan and George S. Lueker's 1976 paper connected graph elimination to symmetric sparse matrices and gave a search-based algorithm for finding a perfect elimination ordering when one exists. Its abstract distinguishes a minimal elimination ordering from a minimum one: removing avoidable fill-in does not by itself minimize the total number of added edges.[ref]