ExamplesBy LevelBy TopicLearning Paths
844 Fundamental

Greedy Algorithm Patterns

Functional Programming

Tutorial Video

Text description (accessibility)

This video demonstrates the "Greedy Algorithm Patterns" functional Rust example. Difficulty level: Fundamental. Key concepts covered: Functional Programming. Greedy algorithms make locally optimal choices at each step, hoping for a global optimum. Key difference from OCaml: | Aspect | Rust | OCaml |

Tutorial

The Problem

Greedy algorithms make locally optimal choices at each step, hoping for a global optimum. Unlike dynamic programming which considers all subproblems, greedy algorithms commit to a choice and never reconsider. When a greedy choice property holds — meaning there always exists an optimal solution that includes the greedy choice — greedy algorithms are correct and typically O(n log n) (dominated by sorting). Classic greedy problems: interval scheduling (schedule maximum activities), fractional knapsack, Huffman coding, Prim's/Kruskal's MST, and coin change (for standard denominations). Recognizing when greedy works (and when it fails) is a key algorithm design skill.

🎯 Learning Outcomes

  • • Identify the greedy choice property: locally optimal → globally optimal
  • • Implement interval scheduling maximization: sort by end time, greedily pick non-overlapping intervals
  • • Implement fractional knapsack: sort by value/weight ratio, greedily fill
  • • Understand exchange argument proofs: show swapping greedy choice for any other cannot improve
  • • Recognize when greedy fails: 0/1 knapsack, coin change with non-standard denominations
  • Code Example

    #![allow(clippy::all)]
    //! Placeholder

    Key Differences

    AspectRustOCaml
    Sort keysort_by_key(|&(_, end)| end)List.sort with comparison fn
    Initializationi32::MINInt.min_int
    Accumulationmut last_end + pushfold_left with acc tuple
    Fractional knapsackSort by v/w with f64Same with float
    Correctness proofExchange argumentSame mathematical argument
    Failure cases0/1 knapsack exampleSame

    OCaml Approach

    OCaml's interval scheduling uses List.sort (fun (_, e1) (_, e2) -> compare e1 e2) then List.fold_left accumulating selected intervals. The greedy decision is if start >= last_end. OCaml's Int.min_int initializes last_end. The fractional knapsack sorts by ratio using List.sort and fills greedily with List.fold_left. OCaml's pattern destructuring let (start, end_) = interval reads naturally. The Printf module formats activity schedules for verification.

    Full Source

    #![allow(clippy::all)]
    //! Placeholder

    Deep Comparison

    OCaml vs Rust: Greedy Algorithm Patterns

    Overview

    See the example.rs and example.ml files for detailed implementations.

    Key Differences

    AspectOCamlRust
    Type systemHindley-MilnerOwnership + traits
    MemoryGCZero-cost abstractions
    MutabilityExplicit refmut keyword
    Error handlingOption/ResultResult<T, E>

    See README.md for detailed comparison.

    Exercises

  • Implement a greedy coin change algorithm and show a denomination set where it fails to find the optimal solution.
  • Implement Huffman coding: build a frequency tree greedily using a min-heap, then assign binary codes.
  • Verify the interval scheduling result: write a checker that confirms no two selected intervals overlap.
  • Implement the activity selection with weighted jobs (maximize total weight, not count) and show greedy fails — requires DP.
  • Implement the job scheduling to minimize lateness: sort by deadline, prove exchange argument for correctness.
  • Open Source Repos