문제
정수 n과 k 그리고 정수배열 n의 길이의 speed와 efficiency가 주어졌습니다. 1부터 n까지 n명의 엔지니어가 있으며 speed[i]와 efficiency[i]는 i번째 엔지니어의 속도와 효율을 의미합니다.
최대 k명의 다른 엔지니어를 n명 중에 선택하여 최대 performance를 낼 수 있는 팀을 만드세요.
팀의 performance는 엔지니어들의 speed를 더한 값에 선택한 엔지니어들 중 최소 efficiency를 곱한 값 입니다.
팀의 최대 performance를 반환하세요. 답이 큰 수일 수 있으니, 답에 modulo \(10^9 + 7\) 연산 후 반환하세요.
예시
Input: n = 6, speed = [2,10,3,1,5,8], efficiency = [5,4,3,9,7,2], k = 2
Output: 60
최대 performance를 낼 수 있는 팀은 엔지니어 2(speed=10 and efficiency=4)와 엔지니어 5(speed=5 and efficiency=7)를 선택하는 것 입니다.
performance는 (10 + 5) * min(4, 7) = 15 * 4 = 60 입니다.
Input: n = 6, speed = [2,10,3,1,5,8], efficiency = [5,4,3,9,7,2], k = 3
Output: 68
위의 예제와 같은 조건이지만 k = 3입니다.
최대 performance를 낼 수 있는 팀은 엔지니어 1과, 엔지니어 2, 그리고 엔지니어 5를 선택하는 것 입니다.
performance = (2 + 10 + 5) * min(5, 4, 7) = 17 * 4 = 68.
Input: n = 6, speed = [2,10,3,1,5,8], efficiency = [5,4,3,9,7,2], k = 4
Output: 72
제약조건
1 <= k <= n <= 105
speed.length == n
efficiency.length == n
1 <= speed[i] <= 10^5
1 <= efficiency[i] <= 10^8
풀이 : Greedy
문제를 쉽게 보고 풀다가 나중에 잘 못 이해한 부분이 있는 것을 확인했습니다 . 이런식의 문제는 처음 풀어보기도 했습니다..
쉽게 오해할 수 있는 부분을 짚고 풀이방식을 설명하며 진행하겠습니다.
최대 k명의 엔지니어를 선택
최대 k명이라는 뜻은 선택된 엔지니어의 수가 k 보다 작을수도 있는 것 입니다.
예를 들어, 엔지니어 1(speed = 10, efficiency = 10)과 엔지니어 2(speed = 1, efficiency = 1)가 있고 k = 2라고 가정합시다.
엔지니어 1 만 고른다면 performance는 100이고 (10 * 10) 엔지니어 2 도 같이 고른다면 11 (11 * 1)입니다.
그렇기에 k명을 넣어서 performance를 계산하는 DFS는 잘못된 접근 이었습니다.
자, 그럼 위의 내용을 고려하며 풀이를 진행하겠습니다.
1. efficiency 기준으로 정렬하기
performance는 선택된 엔지니어 중 최소 efficiency를 곱해줘야 합니다.즉, efficiency가 높을 수록 performance가 커질 확률이 커집니다. 그렇기에 높은 efficiency를 앞으로 올 수 있게 정렬을 합니다.
2. speed에 대해 min heap을 사용하기
priority queue를 사용하여 선택된 엔지니어의 speed를 저장합니다. min heap이기에 제일 위에는 제일 작은 speed가 들어있습니다.
speed는 크면 클 수록 좋기에 k가 넘어가 제거를 할 경우 제일 작은 speed를 빼야합니다.
efficiency로 정렬된 엔지니어를 돌아가며 최대 k명의 엔지니어들을 선택하고 speed를 더해줍니다. 그 후 현재까지 performance와 현재 efficiency에 더해준 speed를 곱한 값과 비교합니다. efficiency가 큰 값부터 작은 값 순으로 들어 있으니 현재 efficiency 값이 최소 efficiency 입니다.
만약 k명이 넘어갈 경우 더해준 speed에서 제일 작은 speed를 빼는데 해당 값은 min heap 제일 위에 저장이 되어 있습니다.
또한, k보다 적게 엔지니어를 선택할 수도 있는데, 이럴경우는 절대적으로 efficiency가 제일 큰 엔지니어들로 구성되지 않으면 성립하지 않습니다. 이 부분이 이해가 애매했었는데 엔지니어 1(speed = 10, efficiency = 10)과 엔지니어 2(speed = 200, efficiency = 1)가 있고 k = 2 일 때 각각 한 명을 고를 경우 performance는 100과 200 입니다.
하지만 둘 다 고를 경우, 1 * 210 = 210 으로 k 이하로 구성할 때 효율이 제일 좋은 엔지니어를 빼면 안된다는 것을 알 수 있습니다.
검증해서 적어보고 싶은데 기회가 생긴다면 진행해보겠습니다.
그리고 모든 경우의 수를 진행한다면 time out이 나게됩니다...
코드는 아래와 같습니다.
class Solution {
public int maxPerformance(int n, int[] speed, int[] efficiency, int k) {
int[][] engineers = new int[n][2];
for (int i = 0; i < n; i++)
engineers[i] = new int[] {efficiency[i], speed[i]};
Arrays.sort(engineers, (a, b) -> Integer.compare(b[0], a[0]));
long speedSum = 0;
long answer = 0;
PriorityQueue<Integer> speedMinHeap = new PriorityQueue<>();
for (int[] engineer : engineers) {
int currEfficiency = engineer[0];
int currSpeed = engineer[1];
if (speedMinHeap.size() >= k)
speedSum -= speedMinHeap.poll();
speedMinHeap.add(currSpeed);
speedSum += currSpeed;
answer = Math.max(answer, speedSum * currEfficiency);
}
return (int)(answer % 1000000007);
}
}
저에게는 hard 다운 문제였습니다.
은근히 DFS나 DP는 조건만 잘걸면 쉽게 풀 수 있는 것 같은데 Greedy는 이해하기 어려울 때가 많은 것 같습니다.
의견 및 질문은 늘 환영합니다 :)
'LeetCode [Java]' 카테고리의 다른 글
[hard] 899. Orderly Queue (0) | 2023.12.14 |
---|---|
[hard] 218. The Skyline Problem (0) | 2023.12.10 |
[medium] 73. Set Matrix Zeroes (1) | 2023.12.10 |
[medium] 39. Combination Sum (0) | 2023.12.09 |
[easy] 70. Climbing Stairs (2) | 2023.12.06 |