Skip to content
Home DSA Greedy Algorithm Introduction

Greedy Algorithm Introduction

Where developers are forged. · Structured learning · Free forever.
📍 Part of: Greedy & Backtracking → Topic 1 of 13
Master Greedy algorithms: learn the greedy choice property, optimal substructure, and why local optimization leads to global success in interval scheduling and Huffman coding.
⚙️ Intermediate — basic DSA knowledge assumed
In this tutorial, you'll learn
Master Greedy algorithms: learn the greedy choice property, optimal substructure, and why local optimization leads to global success in interval scheduling and Huffman coding.
  • Greedy makes the locally optimal choice at each step — no backtracking.
  • Greedy is correct when the problem has the greedy choice property: local optimal = global optimal.
  • Always prove correctness before trusting a greedy solution — or test with edge cases.
✦ Plain-English analogy ✦ Real code with output ✦ Interview questions
Quick Answer

A greedy algorithm makes the locally optimal choice at each step, hoping it leads to a globally optimal solution. Greedy works when the problem has the greedy choice property: a locally optimal choice is also globally optimal. Classic examples include interval scheduling, Dijkstra's algorithm, and Huffman coding. Coin change with arbitrary denominations may require dynamic programming instead.

Interval Scheduling — The Power of the Earliest Finish Time

The Interval Scheduling problem asks: 'Given a set of activities with start and end times, what is the maximum number of non-overlapping activities you can perform?'

Many beginners try to pick the shortest interval or the one that starts earliest, but those fail. The proven greedy choice is to always pick the activity that ends earliest. This leaves the maximum amount of time remaining for all subsequent activities.

IntervalScheduler.java · JAVA
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
package io.thecodeforge.algorithms.greedy;

import java.util.*;

/**
 * Production-grade implementation of the Activity Selection Problem.
 * Time Complexity: O(N log N) due to sorting.
 */
public class IntervalScheduler {
    public static class Interval {
        int start, end;
        public Interval(int start, int end) { this.start = start; this.end = end; }
        @Override
        public String toString() { return "(" + start + ", " + end + ")"; }
    }

    public List<Interval> selectMaxActivities(List<Interval> intervals) {
        if (intervals == null || intervals.isEmpty()) return Collections.emptyList();

        // Greedy Choice: Sort by finish time
        intervals.sort(Comparator.comparingInt(a -> a.end));

        List<Interval> result = new ArrayList<>();
        Interval lastSelected = intervals.get(0);
        result.add(lastSelected);

        for (int i = 1; i < intervals.size(); i++) {
            Interval current = intervals.get(i);
            // If this activity starts after or when the last one ends, pick it
            if (current.start >= lastSelected.end) {
                result.add(current);
                lastSelected = current;
            }
        }
        return result;
    }

    public static void main(String[] args) {
        IntervalScheduler scheduler = new IntervalScheduler();
        List<Interval> input = Arrays.asList(
            new Interval(1, 4), new Interval(3, 5), new Interval(0, 6), 
            new Interval(5, 7), new Interval(3, 8), new Interval(5, 9),
            new Interval(6, 10), new Interval(8, 11), new Interval(12, 16)
        );
        System.out.println("Selected intervals: " + scheduler.selectMaxActivities(new ArrayList<>(input)));
    }
}
▶ Output
Selected intervals: [(1, 4), (5, 7), (8, 11), (12, 16)]

Coin Change — Understanding the Greedy Failure

For a 'canonical' coin system (like USD: 1, 5, 10, 25), the greedy approach of taking the largest coin first is mathematically optimal. However, if a country used coins of 1, 3, and 4 units, greedy would fail to find the best way to make 6 units. Greedy would take a 4, then two 1s (3 coins), whereas the optimal is two 3s (2 coins).

greedy_check.sql · SQL
123456789101112131415
-- io.thecodeforge.analytics
-- Tracking greedy vs optimal counts in a simulated environment
CREATE TABLE denominations (coin_val INT);
INSERT INTO denominations VALUES (1), (3), (4);

-- A simple query to show how many of the LARGEST coin greedy would take
-- for an amount of 6.
SELECT 
    6 AS target_amount,
    MAX(coin_val) AS greedy_first_pick,
    (6 / MAX(coin_val)) AS coins_taken,
    (6 % MAX(coin_val)) AS remainder_to_process
FROM denominations
WHERE coin_val <= 6;
-- This logic clearly shows greedy leaves a remainder of 2, requiring 2 more coins.
▶ Output
target_amount: 6 | greedy_first_pick: 4 | coins_taken: 1 | remainder_to_process: 2

Environment Setup for Algorithm Analysis

To benchmark greedy algorithms against complex DP solutions, we use a containerized environment to ensure consistent CPU/Memory constraints for timing.

Dockerfile · DOCKER
1234567
# io.thecodeforge.infrastructure
FROM eclipse-temurin:17-jdk-jammy
WORKDIR /app
COPY . /app
RUN javac io/thecodeforge/algorithms/greedy/IntervalScheduler.java
# Run with memory limits to test efficiency
CMD ["java", "-Xmx128m", "io.thecodeforge.algorithms.greedy.IntervalScheduler"]
▶ Output
Successfully built greedy-benchmark-container

🎯 Key Takeaways

  • Greedy makes the locally optimal choice at each step — no backtracking.
  • Greedy is correct when the problem has the greedy choice property: local optimal = global optimal.
  • Always prove correctness before trusting a greedy solution — or test with edge cases.
  • Interval scheduling (sort by end time) and Dijkstra are classic correct greedy algorithms.
  • Coin change with arbitrary denominations requires dynamic programming, not greedy.

Interview Questions on This Topic

  • QWhat is the 'Greedy Choice Property' and how does it differ from 'Optimal Substructure'?
  • QLeetCode Standard: Explain how the 'Jump Game' can be solved using a greedy approach. What is the time complexity?
  • QWhy does the greedy approach for the 0/1 Knapsack problem fail while it works for the Fractional Knapsack?
  • QProve why sorting by 'Earliest Start Time' is a sub-optimal greedy strategy for the Interval Scheduling problem.
  • QIn Huffman Coding, what is the greedy choice being made at each step of the tree construction?

Frequently Asked Questions

How do you prove a greedy algorithm is correct?

There are two standard proof methods. First is the 'Exchange Argument': you assume there is an optimal solution different from yours and prove that you can swap its elements with your greedy choices without making it worse. Second is 'Greedy Stays Ahead': you prove that at every step $k$, the greedy solution has progressed further toward the goal than any other possible algorithm.

What is the difference between greedy and dynamic programming?

The core difference is 'commitment.' A Greedy algorithm commits to a choice and never looks back. Dynamic Programming (DP) is more cautious; it calculates the results of all possible choices, stores them (memoization), and then picks the best path. Greedy is faster ($O(N \log N)$ or $O(N)$), while DP is more robust but more expensive ($O(N^2)$ or $O(N imes W)$).

When should I definitely NOT use a Greedy algorithm?

If your current choice significantly limits or dictates your future options in a way that might be suboptimal, Greedy is likely to fail. A classic example is the Fractional Knapsack vs. 0/1 Knapsack. Greedy works for Fractional (you can take bits of items), but fails for 0/1 because taking a heavy, semi-valuable item might prevent you from taking two light, very valuable items later.

Is Dijkstra's algorithm greedy?

Yes. Dijkstra is a greedy algorithm because at each step it picks the 'closest' unvisited vertex to the source, trusting that this local shortest path will contribute to the global shortest path. This is why it fails with negative edge weights—the greedy property is broken.

🔥
Naren Founder & Author

Developer and founder of TheCodeForge. I built this site because I was tired of tutorials that explain what to type without explaining why it works. Every article here is written to make concepts actually click.

Next →Activity Selection Problem
Forged with 🔥 at TheCodeForge.io — Where Developers Are Forged