삘 받아서 한 문제 더 풀어보았습니다.

약 30분 정도 소요되었습니다. 자료구조에서 들었던 min_heap을 priority_queue라는 STL을 통해 아주 쉽게 구현할 수 있다는 것을 알 수 있었습니다.

 

목차

     


    0. 문제 설명

    매운 것을 좋아하는 Leo는 모든 음식의 스코빌 지수를 K 이상으로 만들고 싶습니다. 모든 음식의 스코빌 지수를 K 이상으로 만들기 위해 Leo는 스코빌 지수가 가장 낮은 두 개의 음식을 아래와 같이 특별한 방법으로 섞어 새로운 음식을 만듭니다.

     

    섞은 음식의 스코빌 지수 = 가장 맵지 않은 음식의 스코빌 지수 + (두 번째로 맵지 않은 음식의 스코빌 지수 * 2)

    Leo는 모든 음식의 스코빌 지수가 K 이상이 될 때까지 반복하여 섞습니다.
    Leo가 가진 음식의 스코빌 지수를 담은 배열 scoville과 원하는 스코빌 지수 K가 주어질 때, 모든 음식의 스코빌 지수를 K 이상으로 만들기 위해 섞어야 하는 최소 횟수를 return 하도록 solution 함수를 작성해주세요.

     

    0.0. 제한 사항

    • scoville의 길이는 2 이상 1,000,000 이하입니다.
    • K는 0 이상 1,000,000,000 이하입니다.
    • scoville의 원소는 각각 0 이상 1,000,000 이하입니다.
    • 모든 음식의 스코빌 지수를 K 이상으로 만들 수 없는 경우에는 -1을 return 합니다.

     

    0.1. 입출력 예

     

    scoville K return
    [1, 2, 3, 9, 10, 12] 7 2

     

    0.2. 입출력 예 설명

    1. 스코빌 지수가 1인 음식과 2인 음식을 섞으면 음식의 스코빌 지수가 아래와 같이 됩니다.
      새로운 음식의 스코빌 지수 = 1 + (2 * 2) = 5
      가진 음식의 스코빌 지수 = [5, 3, 9, 10, 12]

    2. 스코빌 지수가 3인 음식과 5인 음식을 섞으면 음식의 스코빌 지수가 아래와 같이 됩니다.
      새로운 음식의 스코빌 지수 = 3 + (5 * 2) = 13
      가진 음식의 스코빌 지수 = [13, 9, 10, 12]

    모든 음식의 스코빌 지수가 7 이상이 되었고 이때 섞은 횟수는 2회입니다.

     


    1. 풀이 과정

     

    priority queue는 기본적으로 max_heap 구조를 가지고 있습니다.(heap의 맨 꼭대기에 가장 큰 값이 오는 구조)

    이걸 min_heap 형태로 바꿔주기 위해서는 greater<int>인자를 세 번째 파라미터로 받아주면 됩니다.

     

    이것만 만들 수 있으면 pop()을 통해 가장 작은 2개를 뽑아서 계산을 해준 후에 다시 넣어주는 것을 반복하면 됩니다.

    계산을 몇 번 했는지가 answer이기 때문에 while문 안에 계산을 할 때마다 answer을 1씩 증가시켜줘야 합니다.

     

    그렇게 반복하다가 가장 작은 수가 K를 넘으면 answer를 return하면 되고, 만약 하나가 남아서 더이상 계산이 불가능하다면 그 값을 입력받은 K와 비교하고, K보다 작으면 -1을 return해주면 되는 것이죠. 

     


    2. 소스 코드

     

    2.0. 정답인 소스코드

    #include <string>
    #include <vector>
    #include <queue>
    
    using namespace std;
    
    int solution(vector<int> scoville, int K) {
        int answer = 0;
        priority_queue<int, vector<int>, greater<int>> pq;
        int size = scoville.size();
        for (int i = 0; i < size; ++i)
            pq.push(scoville[i]);
        
        if(pq.top() > K) // 애초부터 min_heap이 K를 넘으면 그대로 0 return
            return answer;
        
        while (pq.size() != 1 && pq.top() < K){
            int f = pq.top();
            pq.pop();
            int s = pq.top();
            pq.pop();
            int cal = f+s*2;
            pq.push(cal);
            ++answer;
        }
        if (pq.size() == 1 && pq.top() < K)
            answer = -1;
        return answer;
    }

     

     

    2.1. <부록> 사소한 실수..

     

    마지막 if문에서 size 대신 top을 넣어버렸더니 오류가 발생합니다.

    -1인 경우를 제대로 체크하지 못하게 되는데 신기하게 효율성 테스트는 다 통과했네요 ㅋㅋㅋㅋ

    #include <string>
    #include <vector>
    #include <queue>
    
    using namespace std;
    
    int solution(vector<int> scoville, int K) {
        int answer = 0;
        priority_queue<int, vector<int>, greater<int>> pq;
        int size = scoville.size();
        for (int i = 0; i < size; ++i)
            pq.push(scoville[i]);
        
        if(pq.top() > K) // 애초부터 min_heap이 K를 넘으면 그대로 0 return
            return answer;
        
        while (pq.size() != 1 && pq.top() < K){
            int f = pq.top();
            pq.pop();
            int s = pq.top();
            pq.pop();
            int cal = f+s*2;
            pq.push(cal);
            ++answer;
        }
        if (pq.top() == 1 && pq.top() < K)
            answer = -1;
        return answer;
    }

     


    3. 후기

     

    priority queue를 처음 사용해봤습니다. 이런 것도 쓸 수 있게 되었다니 참 신기합니다! 앞으로 문제들이 많은데 힙 문제에서는 대부분 priority queue를 사용하겠죠? 재미있을 것 같아서 굉장히 기대됩니다 ^^

     

    출처 : 프로그래머스 코딩테스트 연습, programmers.co.kr/learn/courses/30/lessons/42626

    반응형
    • 네이버 블로그 공유하기
    • 네이버 밴드에 공유하기
    • 페이스북 공유하기
    • 카카오스토리 공유하기