Algorithm|Javascript Algorithm

마시멜로를 못 참는 탐욕 알고리즘

0

크리스가 편의점에서 아르바이트를 하고 있다.

손님이 1260원짜리 물건을 사고 2000원을 냈다. 거스름돈은 740원.

점장님이 신신당부했다. "동전 개수를 최소한으로 해서 거슬러 줘. 동전 아까우니까."

크리스는 고민하지 않고 손을 움직였다.

  • 가장 큰 500원짜리부터 집는다. (남은 돈 240원)
  • 그다음 큰 100원짜리 두 개를 집는다. (남은 돈 40원)
  • 마지막으로 10원짜리 네 개를 집는다. (끝!)
  • 크리스는 본능적으로 알고리즘을 사용했다.

    "지금 당장 선택할 수 있는 것 중 가장 좋은 것(가장 큰 동전)을 고른다."

    이것이 바로 **탐욕 알고리즘(Greedy Algorithm)**이다.

    1. "지금 이 순간"에 충실해라

    동적 프로그래밍(DP)이 "모든 가능성을 기록하며 신중하게 미래를 설계하는 모범생"이라면,

    탐욕 알고리즘은 **"미래는 모르겠고, 일단 지금 눈앞에 보이는 이득을 챙기는 욜로(YOLO)족"**이다.

  • 1단계: 선택의 순간마다 당장 눈앞에 보이는 최선(Local Optimal)을 선택한다.
  • 2단계: 한 번 선택하면 절대 뒤를 돌아보거나 번복하지 않는다.
  • 3단계: 그 선택들이 모여서 전체의 최선(Global Optimal)이 되기를 기도한다.
  • 2. 성공 사례: 거스름돈 문제

    크리스가 푼 거스름돈 문제는 탐욕 알고리즘이 완벽하게 통하는 대표적인 사례다.

    우리나라 동전(500, 100, 50, 10)은 큰 단위가 항상 작은 단위의 배수이기 때문이다.

    JavaScript

    function minCoins(change) { const coins = [500, 100, 50, 10]; // 큰 동전부터 정렬 let count = 0; for (let coin of coins) { // 1. 당장 이 동전으로 최대한 많이 거슬러 준다. count += Math.floor(change / coin); // 2. 남은 돈을 계산한다. change %= coin; } return count; } console.log(minCoins(740)); // 7 (500x1 + 100x2 + 10x4)

    복잡한 재귀나 점화식 없이 반복문 하나로 끝난다. 속도가 엄청나게 빠르다.

    3. 실패 사례: 탐욕의 함정

    하지만 세상일이 항상 맘대로 되지는 않는다.

    만약 동전 단위가 **[500원, 400원, 100원]**이라고 가정해 보자.

    손님이 800원을 거슬러 받아야 한다면?

  • 탐욕 알고리즘의 선택:
  • 실제 정답:
  • 탐욕 알고리즘은 당장의 500원에 눈이 멀어, 400원 두 개라는 더 좋은 수를 놓쳤다.

    이럴 때는 탐욕 알고리즘을 쓸 수 없고, 우리가 지난 시간에 배운 **동적 프로그래밍(DP)**을 써야 한다.

    4. 언제 써야 할까? (탐욕적 선택 조건)

    탐욕 알고리즘은 빠르고 강력하지만, 치명적인 단점(항상 최적해를 보장하지 않음) 때문에 사용 조건이 까다롭다.

  • 탐욕적 선택 속성 (Greedy Choice Property): 앞의 선택이 이후의 선택에 나쁜 영향을 주지 않아야 한다. (500원을 먼저 꺼낸다고 해서 나중에 손해 볼 일이 없어야 함)
  • 최적 부분 구조 (Optimal Substructure): 부분의 최적해가 모이면 전체의 최적해가 되어야 한다.
  • 실무에서 쓰이는 곳

  • 최단 경로 구하기 (다익스트라 알고리즘): 네비게이션에서 가장 빠른 길을 찾을 때, "일단 여기서 가장 가까운 도시로 이동"하는 방식을 기반으로 한다.
  • 최소 신장 트리 (크루스칼/프림): 지난 3장에서 배운 "가장 싼 케이블부터 연결하기"가 바로 탐욕 알고리즘이다.
  • 데이터 압축 (허프만 코딩): 파일 용량을 줄일 때 빈도가 높은 문자에 짧은 코드를 부여한다.
  • 5. 5장을 마치며

    우리는 이제 알고리즘의 주요 패러다임을 모두 섭렵했다.

  • 무식하게 다 해보기 (Brute Force)
  • 똑똑하게 나눠서 풀기 (Divide and Conquer)
  • 기억해서 효율 높이기 (Dynamic Programming)
  • 지금 당장 최선 고르기 (Greedy)
  • 하지만 알고리즘의 세계에는 정답이 없는 문제들도 있다. 슈퍼컴퓨터로도 몇 억 년이 걸리는 문제들, 그리고 그걸 해결하기 위해 인간이 고안해 낸 기발한 꼼수들.

    마지막 6장에서는 전설적인 난제, N-Queen 문제NP 문제 이야기를 통해 알고리즘적 사고의 끝을 경험해 보자.

    6장 그 밖의 문제들 - 1. N-Queen 문제 편에서 계속된다.


    🔗 참고 링크

  • Greedy Algorithm - GeeksforGeeks
  • VisualAlgo - Greedy
  • 댓글 (0)

    0/1000
    댓글을 불러오는 중...