로직
우선, 큐에 [음식 양, 음식 번호] 를 넣고 음식양이 오름차순이 되도록 정렬한다.
예를 들어, [1, 2], [2, 3], [3, 1]이 있다고 가정하자.
- 처음 꺼낸 리스트는 [1, 2]가 된다.
- 음식양 1을 전체 리스트의 길이(3)만큼 먹는다. 하지만 1*3은 k보다 작으므로 더 진행
- 두번째 꺼낸 리스트는 [2, 3]이 된다.
- 전에 1만큼 먹었기 때문에 2-1 = 1이 된다.
- 음식양 1을 전체 리스트의 길이(2)만큼 먹는다. 그럼 지금까지 3 + 2를 먹었다. 이는 k와 같으므로 리스트를 다시 넣어주고 종료한다.
(지금까지 먹은양이 k보다 크다는 의미는 이번 음식이 없어지면서 또는 없어지기 전에 k만큼 먹었다고 할 수 있다.)
종료 시점에 리스트의 번호만 보면 [1, 3]이 남는다.
위 상황에서는 k만큼 먹고 다음 번호인 1을 출력한다.
주의 사항
우선 순위 큐 사용
- 처음에는 List에 담고 음식 양 순으로 정렬 -> 음식 번호 순으로 정렬해 답을 도출했다. 하지만 시간복잡도에 문제가 생긴다.
- 우선순위큐를 활용해 데이터를 넣고 마지막에 리스트로 만들어주고 한번만 정렬해 시간복잡도를 줄였다.
long 사용
- 음식의 값은 각 1000만까지 가질 수 있다. 따라서 음식의 합은 long처리를 해주어야 한다.
반환을 -1로 하는 경우
- 모든 음식의 양이 k보다 작거나 같다면 다음에 먹을 음식이 없으므로 -1을 반환해야 한다.
코드
import java.util.*;
class Solution {
public int solution(int[] food_times, long k) {
int len = food_times.length;
long sum = 0;
PriorityQueue<List<Integer>> queue
= new PriorityQueue<>(Comparator.comparing(arr -> arr.get(0)));
for(int i=0; i<len; i++){
queue.add(Arrays.asList(food_times[i], i+1));
sum += food_times[i];
}
if(sum <= k){
return -1;
}
long before_value = 0;
long sum_value = 0;
while(true){
List<Integer> now = queue.poll();
int now_value = now.get(0);
if(sum_value + (now_value-before_value)*len >= k){
queue.add(now);
break;
}
sum_value += (now_value-before_value)*len;
len -= 1;
before_value = now_value;
}
List<List<Integer>> result = new ArrayList<>(queue);
Collections.sort(result, Comparator.comparing(arr -> arr.get(1)));
int index = (int)((k-sum_value)%len);
return result.get(index).get(1);
}
}
'Algorithm > Practice' 카테고리의 다른 글
이코테 - 안테나 with JAVA (0) | 2023.09.04 |
---|---|
이코테 - 특정 거리의 도시 찾기 with JAVA (0) | 2023.08.16 |
이코테 - 만들 수 없는 금액 with JAVA (0) | 2023.08.09 |
Programmers - 등산 코스 정하기 with JAVA (0) | 2023.08.06 |
Programmers - 블록 이동하기 with JAVA (0) | 2023.08.06 |