Java
프로그래머스: 귤 고르기(우선순위 큐 Priority Queue)
Daeryuk Kim
2024. 3. 6. 00:20
import java.util.*;
class Solution {
public int solution(int k, int[] tangerine) {
/*
예를 들어, 경화가 수확한 귤 8개의 크기가
[1, 3, 2, 5, 4, 5, 2, 3] 이라고 합시다.
경화가 귤 6개를 판매하고 싶다면,
크기가 1, 4인 귤을 제외한 여섯 개의 귤을 상자에 담으면,
귤의 크기의 종류가 2, 3, 5로 총 3가지가 되며
이때가 서로 다른 종류가 최소일 때입니다.
*/
Map<Integer, Integer> map = new HashMap<>();
for (int t : tangerine) {
map.put(t, map.getOrDefault(t, 0) + 1);
}
PriorityQueue<Integer> pq = new PriorityQueue<>((a, b) -> map.get(b) - map.get(a));
pq.addAll(map.keySet());
int count = 0;
while (k > 0) {
/*
[2, 5, 3, 4, 1]
t = 2
[5, 1, 3, 4]
t = 5
[3, 1, 4]
t = 3
반환값: 3
*/
int t = pq.poll();
int num = Math.min(map.get(t), k);
// 맵에 있는 값 재 업데이트
map.put(t, map.get(t) - num);
//총 k개만 담을 수 있으니까, 담은 사이즈 개수는 k에서 빼줘야겠지? ㅇㅇ
k -= num;
if (map.get(t) > 0) {
pq.add(t);
}
count++;
}
return count;
}
public static void main(String[] args) {
int k = 6;
int[] tangerine = {1, 3, 2, 5, 4, 5, 2, 3};
Solution sol = new Solution();
int result = sol.solution(k, tangerine);
System.out.println(result);
}
}
이 문제의 핵심은 "k개의 귤을 고를 때, 가능한 한 다양한 종류의 귤을 적게 선택하려면 어떻게 해야 하는가?"입니다.
이를 위해 우선 각 귤 크기별로 개수를 세어 Map에 저장합니다. 이 Map의 key는 귤의 크기, value는 해당 크기의 귤 개수입니다.
그 다음, 우선순위 큐를 사용하여 가장 많은 개수를 가진 귤 크기부터 선택합니다. 우선순위 큐는 항상 가장 우선순위가 높은 원소를 먼저 반환합니다. 이 경우, 우선순위는 귤의 개수이며, 많은 개수를 가진 귤이 높은 우선순위를 가집니다.
이제 k개의 귤을 고를 때까지 다음 과정을 반복합니다:
- 우선순위 큐에서 가장 많은 개수를 가진 귤을 선택합니다.
- 선택한 귤의 개수와 남아있는 귤(k) 중 작은 수만큼 귤을 고릅니다.
- 고른 귤의 개수만큼 k를 줄이고, 고른 귤의 개수를 Map에서 빼줍니다.
- 만약 고른 귤이 아직 Map에 남아있다면, 다시 우선순위 큐에 넣습니다.
- 고른 귤의 종류 수를 세서 count에 더합니다.
이 과정을 반복하면, k개의 귤을 고를 때 크기가 서로 다른 종류의 수의 최솟값을 구할 수 있습니다. 이 값이 곧 함수의 반환값이 됩니다.