https://programmers.co.kr/learn/courses/30/lessons/42626
매운 것을 좋아하는 Leo는 모든 음식의 스코빌 지수를 K 이상으로 만들고 싶습니다. 모든 음식의 스코빌 지수를 K 이상으로 만들기 위해 Leo는 스코빌 지수가 가장 낮은 두 개의 음식을 아래와 같이 특별한 방법으로 섞어 새로운 음식을 만듭니다.
섞은 음식의 스코빌 지수 = 가장 맵지 않은 음식의 스코빌 지수 + (두 번째로 맵지 않은 음식의 스코빌 지수 * 2)
Leo는 모든 음식의 스코빌 지수가 K 이상이 될 때까지 반복하여 섞습니다.Leo가 가진 음식의 스코빌 지수를 담은 배열 scoville과 원하는 스코빌 지수 K가 주어질 때, 모든 음식의 스코빌 지수를 K 이상으로 만들기 위해 섞어야 하는 최소 횟수를 return 하도록 solution 함수를 작성해주세요.
최소 힙(우선순위 큐)을 이용해서 문제를 접근하고 해결을 위한 세 가지 조건을 먼저 구성했다.
PriorityQueue<Integer> pq = new PriorityQueue<>();
//우선 순위 큐에 데이터 넣기
for(int scv : scoville)
pq.offer(scv);
우선 순위 큐에 들어간 원소들은 항상 완전 이진 트리를 구성하며, (최소 힙의 경우) 최소 값이 트리의 루트에 들어가고 큐에 원소가 삽입될 때 항상 트리의 단말 노드로 들어가 부모 노드와 비교해 삽입된 원소가 더 작으면 swap해주며 구성된다.
👉🏻첫번째 조건 확인 👈🏻
10,7,8,5,9
로 구성된 scoville배열이 주어지고, K값이 5인 경우를 예로 들어보자.
큐에 원소를 삽입하면 {5,8,7,10,9}
순으로 노드가 삽입된다. 우선순위 큐에서 가장 앞 원소가 5이고 최소값이면서 K와 같기 때문에 음식을 섞어줄 필요가 없다. 따라서 count(0)을 return하면 된다.
//큐 size가 1인 경우 값 비교만 필요
//큐의 가장 최소 값이 K 이상인 경우 음식 섞어줄 필요 x
while(pq.size()>1 && pq.peek() < K)
👉🏻두번째 조건 확인 👈🏻
큐의 size가 1인경우에는 while문의 조건을 들어가지 않기 때문에 음식을 섞어줄 필요가 없다. 따라서 값이 K보다 큰지 작은지만 비교해서 -1 혹은 count(0)를 return 해주면 된다.
if(pq.peek() < K )
return -1;
👉🏻세번째 조건 확인 👈🏻
3,2,4,6,1
로 구성된 scoville배열이 주어지고, K값이 14인 경우를 예로 들어보자.
큐에 원소를 삽입하면 {1,2,4,6,3}
순으로 노드가 삽입된다. 우선순위 큐에서 가장 작은 원소 1과 그다음 작은 원소 2를 문제의 공식대로 음식을 섞어주면 1 + (2*2) = 5가 되고 다시 우선순위 큐에 넣어준다. 그렇다면 {2,3,4,6,5}
가 된다. 이러한 방식을 가장 앞 원소가 K보다 크거나 같은 수가 될 때까지 반복하고 반복횟수를 세어서 return해주면 된다.
아래는 Java로 구현한 코드이다.
package com.algorithm.Programmers.Lv2;
import java.util.PriorityQueue;
public class Solution_42626 {
public static void main(String[] args) {
int[] scoville = {3,2,4,6,1};
int k = 14;
System.out.println(solution(scoville,k));
}
public static int solution(int[] scoville, int K) {
int answer = 0;
PriorityQueue<Integer> pq = new PriorityQueue<>();
//우선 순위 큐에 데이터 넣기
for(int scv : scoville)
pq.offer(scv);
for(int s : pq)
System.out.println(s);
//큐 size가 1인 경우 값 비교만 필요
//큐의 가장 최소 값이 K 이상인 경우 음식 섞어줄 필요 x
while(pq.size()>1 && pq.peek() < K){
int first = pq.poll();
int afterScov = 0;
//최소 값이 K 보다 작으면 음식 섞기
if(pq.peek() < K){
afterScov = first + (pq.poll() * 2);
pq.offer(afterScov);
answer++;
continue;
}
//최소 값이 K보다 큰 경우 마지막으로 음식 섞어주기
afterScov = first + (pq.peek() * 2);
pq.offer(afterScov);
answer++;
}
//최소 값이 기대 스코빌 지수보다 작으면 만들 수 없는 경우
if(pq.peek() < K )
return -1;
return answer;
}
}