TIL/Algorithm

[99클럽 코테 스터디 17일차 TIL] 프로그래머스 | Greedy 구명보트

ujum 2024. 6. 5. 19:52
728x90

17일차 - Greedy

Problem

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

Sol

limit가 있는 보트에 최대 2명까지 태울때, 주어진 people을 모두 태우기 위해 필요한 최소한의 보트 수를 구하는 문제

 

Greedy Algorithm 

 

전역적 최적해를 찾기 위해 각 단계에서 최선의 지역적 선택을 하는 알고리즘

  • 현재 상황에서 가장 최선의 선택을 반복적으로 하는 방식
  • 각 단계에서의 가장 좋은 선택 ➡ 전체 문제의 최적 해
    1.  탐욕 선택 속성 Greedy Choice Property
      • 미래 결과를 고려하지 않고 현재 이용 가능한 정보를 기반으로 결정 == 항상 가장 최적이 아닐수도!
    2. 최적 부분 구조 Optimal Substructure
      • 경험적 접근 : 부분 문제를 해결하여 얻은 해가 전체 문제의 최적 해 보장
    3. 대표 예 : Fractional Knapsack Problem(배낭문제), Dijkstra, Kruskal, Coin Change Problem, Huffman Coding
  • 장점
    • 간단하고 이해하기 쉬움 , 직관적
    • 빠른 실행시간
    • 최적의 솔루션을 찾기 어려운 경우에도 좋은 근사 솔루션 제공 가능
  • 한계/단점
    • 항상 최상의 솔루션을 찾는 것은 아님
    • 순서가 결과에 큰 영향을 미칠 수 있음
    • 국소적 최적화에 중점을 두기 때문에 더 넓은 맥락을 고려해야함
    • Greedy(탐욕스러운)한 선택이 최적의 솔루션으로 이어지지 않는 문제에는 탐욕 알고리즘을 적용할 수 없음(모든 문제에 적용 불가)

 

🌱 참고

 

Greedy Algorithms - GeeksforGeeks

A Computer Science portal for geeks. It contains well written, well thought and well explained computer science and programming articles, quizzes and practice/competitive programming/company interview Questions.

www.geeksforgeeks.org

 

 

Greedy Algorithm Tutorial - Examples, Application and Practice Problem - GeeksforGeeks

A Computer Science portal for geeks. It contains well written, well thought and well explained computer science and programming articles, quizzes and practice/competitive programming/company interview Questions.

www.geeksforgeeks.org

 

 

해결 방법

👀 가장 무거운 사람과 가장 가벼운 사람을 짝지어 구명보트에 태우는 방식으로 접근하였습니다.

1. people의 몸무게 정렬 : 가벼운 몸무게부터 무거운 몸무게까지 오름차순으로 정렬합니다.

2. 양 끝에서 시작 : 가장 가벼운 사람을 가리키는 포인터는 'light', 가장 무거운 사람을 가리키는 포인터는 'heavy'입니다. 초기에 'light'는 0을, 'heavy'는 마지막 인덱스를 가리킵니다.

3. 최대한 많은 사람 태우기 : 'light'와 'heavy'를 더해서 limit을 넘지 않으면 함께 태우고 그렇지 않으면 무거운 사람만 태웁니다. 

4. 포인터 이동 : 두 사람을 모두 태웠다면 'light'와 'heavy'를 각각 +1, -1 해주고, 한 사람만 태웠다면 무거운 사람만 태우기로했기 때문에 'heavy'만 -1 해줍니다.

5. 보트 수 증가 : 보트 수를 증가시켜 필요한 최소 boat 수를 카운트합니다.

6. 반복  : 주어진 people을 모두 태울 때 까지 위의 과정을 반복합니다. 

 

시간복잡도 O(nlogn)
  • 몸무게 배열 정렬 O(nlogn)
  • 배열 순회 O(n)

✔ Answer

def solution(people, limit):
    # 1. 몸무게를 오름차순으로 정렬
    people.sort()
    light = 0
    heavy = len(people) - 1
    boats = 0
    
    # 2. 양 끝에서 시작하여 가장 가벼운 사람과 가장 무거운 사람 태워보기
    while light <= heavy:
        # 3. 최대한 많이 태우기
        
        # 가장 무거운 사람과 가장 가벼운 사람을 함께 태울 수 있는 경우
        if people[light] + people[heavy] <= limit:
        # 4. 포인터 이동
            light += 1
            
        # 가장 무거운 사람을 태우는 경우
        heavy -= 1
        
        # 5. 보트 하나 사용
        boats += 1
    
    return boats






💬 욕심쟁이 알고리즘을 공부하다보니 동적프로그래밍이랑 같이 비교해서 상황에 맞는 알고리즘을 사용하는 것이 필요하다는 것을 알았습니다. 내일 문제를 보고 Greedy 와 DP 비교를 하는 글을 적어보겠습니다! 그리고 다른 분들의 풀이를 보면서 더 다양한 해결 방법을 생각해볼 수 있었습니다.