발행일

[ZBF] 6월 16일 코딩 테스트: 탐욕법

[ZBF] 6월 16일 코딩 테스트: 탐욕법

이 글은 네이버 블로그에 2024년 6월 16일에 올렸던 것을 그대로 옮겨온 것입니다.

탐욕법(Greedy Algorithm)은 매 순간 가장 최적이라고 생각되는 선택을 하는 알고리즘입니다. 최적해를 보장하지는 않지만, 많은 경우 근사해를 빠르게 구할 수 있습니다.

탐욕법 (Greedy Algorithm)란?

탐욕법은 매 단계에서 가장 최적이라고 생각되는 선택을 함으로써 문제를 해결하는 알고리즘입니다. 각 단계에서의 선택이 최종 해답을 보장하지는 않지만, 많은 문제에서 효과적인 방법입니다.

탐욕법의 특징

  1. 단순함: 구현이 간단하고 직관적입니다.
  2. 빠른 실행 시간: 각 단계에서 최적의 선택을 하므로 빠르게 근사해를 구할 수 있습니다.
  3. 지역 최적화: 매 순간의 선택이 전체적으로도 최적이라는 보장은 없지만, 많은 문제에서 유효합니다.

탐욕법의 예

예제 1: 거스름돈 문제

가장 적은 동전의 수로 거스름돈을 주는 문제입니다.

// 거스름돈 문제 예제
function minCoins(coins, amount) {
    let count = 0;
    for (let i = 0; i < coins.length; i++) {
        while (amount >= coins[i]) {
            amount -= coins[i];
            count++;
        }
    }
    return count;
}

let coins = [25, 10, 5, 1];
let amount = 63;
console.log(minCoins(coins, amount)); // 6 (25*2 + 10*1 + 1*3)

예제 2: 활동 선택 문제

여러 활동이 주어졌을 때, 가장 많은 활동을 선택하는 문제입니다.

// 활동 선택 문제 예제
function selectActivities(activities) {
    activities.sort((a, b) => a.end - b.end);
    let selected = [];
    let lastEndTime = 0;

    for (let i = 0; i < activities.length; i++) {
        if (activities[i].start >= lastEndTime) {
            selected.push(activities[i]);
            lastEndTime = activities[i].end;
        }
    }

    return selected;
}

let activities = [
    { start: 1, end: 4 },
    { start: 3, end: 5 },
    { start: 0, end: 6 },
    { start: 5, end: 7 },
    { start: 3, end: 9 },
    { start: 5, end: 9 },
    { start: 6, end: 10 },
    { start: 8, end: 11 },
    { start: 8, end: 12 },
    { start: 2, end: 14 },
    { start: 12, end: 16 }
];

console.log(selectActivities(activities)); 
// [{ start: 1, end: 4 }, { start: 5, end: 7 }, { start: 8, end: 11 }, { start: 12, end: 16 }]

예제 3: 배낭 문제 (Fractional Knapsack Problem)

물건을 쪼갤 수 있을 때, 최대 가치를 얻도록 배낭에 물건을 담는 문제입니다.

// 배낭 문제 예제
function fractionalKnapsack(items, capacity) {
    items.sort((a, b) => (b.value / b.weight) - (a.value / a.weight));
    let totalValue = 0;

    for (let i = 0; i < items.length; i++) {
        if (capacity - items[i].weight >= 0) {
            capacity -= items[i].weight;
            totalValue += items[i].value;
        } else {
            totalValue += items[i].value * (capacity / items[i].weight);
            break;
        }
    }

    return totalValue;
}

let items = [
    { value: 60, weight: 10 },
    { value: 100, weight: 20 },
    { value: 120, weight: 30 }
];

let capacity = 50;
console.log(fractionalKnapsack(items, capacity)); // 240

탐욕법의 시간 복잡도

탐욕법의 시간 복잡도는 문제에 따라 다르지만, 일반적으로 O(n log n)에서 O(n) 사이입니다. 이는 탐욕법이 매 단계에서 최적의 선택을 하기 위해 정렬 등의 연산을 수행하기 때문입니다.

탐욕법의 장단점

장점

  • 간단하고 직관적: 구현이 쉽고 이해하기 쉽습니다.
  • 빠른 실행 시간: 각 단계에서 최적의 선택을 하므로 빠르게 근사해를 구할 수 있습니다.
  • 실용성: 많은 실생활 문제에서 유용하게 사용할 수 있습니다.

단점

  • 최적해 보장 어려움: 항상 최적해를 보장하지 않습니다.
  • 문제 특수성: 특정 문제에만 유용하며, 모든 문제에 적용할 수 없습니다.

탐욕법의 활용

탐욕법은 다음과 같은 상황에서 유용합니다.

  • 문제의 특성상 매 순간 최적의 선택이 전체 최적해로 이어질 때
  • 최적해가 필요하지 않고 근사해도 충분할 때
  • 빠른 해결이 필요할 때

https://school.programmers.co.kr/learn/courses/30/parts/12244

  • 프로그래머스 스쿨 - 온라인 IT 특화 교육 전문 플랫폼 — 프로그래머스 스쿨은 IT 분야 교육 전반의 과정을 제공하는 온라인 교육 플랫폼입니다. 프로그래밍, 데이터, 인공지능 등의 학습부터 코딩 테스트, 과제 테스트 연습까지, 프로그래머스 스쿨과 함께 성장해 보세요!