개요
- 하드 디스크는 한 번에 하나의 작업만 수행할 수 있다.
- 우선순위 디스크 컨트롤러를 구현해야한다.
- 어떤 작업 요청이 들어왔을 때, 작업의 번호, 작업의 요청 시각, 작업의 소요 시간을 저장해 두는 대기 큐가 존재.
- 이 큐는 처음에는 비어있다.
- 디스크 컨트롤러는 하드디스크가 쉬고 있고, 대기 큐에 작업이 있을경우 우선순위가 높은 작업을 디스크에게 수행시킨다.
- 우선순위가 높은 것: 작업의 소요시간이 짧은 것, 작업의 요청 시각이 빠른 것, 작업의 번호가 작은 것
- 하드디스크는 작업을 한 번 시작하면 작업을 마칠 때까지 그 작업만 수행한다.
- 하드디스크는 작업을 마치자마자 바로 다음 작업 수행이 가능하다.
- 각 작업에 대한 반환 시간: 작업 요청부터 종료까지 걸린 시간
<조건>
- 알 수 없음
<입력>
- 작업의 정보가 담겨있는 int[][] jobs
- jobs의 길이: 1 ~ 500
- jobs[i]: [작업이 요청되는 시점, 작업의 소요시간]
- 작업이 요청되는 시점: 0 ~ 1,000
- 작업의 소요시간: 1 ~ 1,000
<반환>
- 모든 요청 작업의 반환 시간의 평균을 반환하라.
문제 풀이
나는 이 문제를 풀기위해 우선순위 큐와 List를 정렬하기 위해 따로 Class와 Comparator를 만들었었다.
https://dmoritle.tistory.com/entry/하드디스크-컨트롤러
[Java] 프로그래머스: 하드디스크 컨트롤러
개요하드 디스크는 한 번에 하나의 작업만 수행할 수 있다.우선순위 디스크 컨트롤러를 구현해야한다.어떤 작업 요청이 들어왔을 때, 작업의 번호, 작업의 요청 시각, 작업의 소요 시간을 저장
dmoritle.tistory.com
그런데, 다른 분의 풀이를 보니
람다식을 사용하여 매우 짧은 풀이를 하셨길래 배워보고자 한다.
먼저 List로 작업을 시간 순으로 정렬하고 관리했던 나와는 다르게
// 작업이 요청되는 시점 기준으로 오름차순 정렬
Arrays.sort(jobs, (o1, o2) -> o1[0] - o2[0]);
...
int jobs_index = 0; // 작업 배열 인덱스
int finish_job = 0; // 처리 완료된 작업 개수
위와 같이 원래 주어진 배열을 람다식으로 정렬하셨다.
또한, 인덱스를 사용해서 남은 작업을 관리하셨다.
또한 의문점이 들면서도 신기한게
작업의 소요시간 기준으로만 오름차순 정렬을 하셨는데,
지문에 따르면 작업은 소요시간, 요청시간, 번호를 기준으로 오름차순 정렬되어야 한다.
아마 테스트케이스에서 소요시간만으로도 구분이 되어서 통과하는 것 같기도 하고...
확실히 프로그래머스는 백준에 비해 테스트케이스가 널널하다.
// 작업의 소요시간 기준으로 오름차순 정렬
PriorityQueue<int[]> pq = new PriorityQueue<>((o1, o2) -> o1[1] - o2[1]);
이 아래는 while문 로직
내 기존 풀이와 비슷하면서도 더 효율적이다.
난 첫 번째 작업을 넣는 걸 while문 앞에서 따로 빼주었는데, 이걸 while문에 합치는 쪽이 훨씬 깔끔한 거 같다.
int jobs_index = 0; // 작업 배열 인덱스
int finish_job = 0; // 처리 완료된 작업 개수
int end_time = 0; // 작업 처리 완료 시간
while(true) {
if(finish_job == jobs.length) break; // 모든 작업을 처리했다면 종료
// 이전 작업 처리 중 요청된 작업 add
while(jobs_index < jobs.length && jobs[jobs_index][0] <= end_time) {
pq.add(jobs[jobs_index++]);
}
if(!pq.isEmpty()) { // 이전 작업 처리 중 요청된 작업이 있는 경우
int[] job = pq.poll();
answer += end_time - job[0] + job[1]; // 작업 요청부터 종료까지 걸린 시간 추가
end_time += job[1]; // 작업 처리 완료 시간 갱신
finish_job++; // 처리 완료된 작업 개수 1 증가
} else { // 이전 작업 처리 중 요청된 작업이 없는 경우
end_time = jobs[jobs_index][0]; // 다음 작업 요청 시점으로 갱신
}
}
전체 코드
import java.util.*;
class Solution {
public int solution(int[][] jobs) {
int answer = 0;
// 작업이 요청되는 시점 기준으로 오름차순 정렬
Arrays.sort(jobs, (o1, o2) -> o1[0] - o2[0]);
// 작업의 소요시간 기준으로 오름차순 정렬
PriorityQueue<int[]> pq = new PriorityQueue<>((o1, o2) -> o1[1] - o2[1]);
int jobs_index = 0; // 작업 배열 인덱스
int finish_job = 0; // 처리 완료된 작업 개수
int end_time = 0; // 작업 처리 완료 시간
while(true) {
if(finish_job == jobs.length) break; // 모든 작업을 처리했다면 종료
// 이전 작업 처리 중 요청된 작업 add
while(jobs_index < jobs.length && jobs[jobs_index][0] <= end_time) {
pq.add(jobs[jobs_index++]);
}
if(!pq.isEmpty()) { // 이전 작업 처리 중 요청된 작업이 있는 경우
int[] job = pq.poll();
answer += end_time - job[0] + job[1]; // 작업 요청부터 종료까지 걸린 시간 추가
end_time += job[1]; // 작업 처리 완료 시간 갱신
finish_job++; // 처리 완료된 작업 개수 1 증가
} else { // 이전 작업 처리 중 요청된 작업이 없는 경우
end_time = jobs[jobs_index][0]; // 다음 작업 요청 시점으로 갱신
}
}
return answer / jobs.length;
}
}
배운 점
Comparator를 람다식으로 구현하는 방법에 대해 배울 수 있었다.
(o1, o2) -> o1[index] - o2[index]
위와 같은 형태의 람다식을 잘 기억해두자.
'Problem Solving > [Java] Programmers' 카테고리의 다른 글
[Java] 프로그래머스: 베스트앨범 (1) | 2025.01.18 |
---|---|
[Java] 프로그래머스: 디스크 컨트롤러 (0) | 2025.01.18 |
[Java] 프로그래머스: 가장 큰 수 (0) | 2025.01.18 |
[Java] 프로그래머스: K번째수 (0) | 2025.01.18 |
[Java] 프로그래머스: 전화번호 목록 (0) | 2025.01.12 |