Skip to content

Commit bced1a0

Browse files
committed
[level 3] Title: 디스크 컨트롤러, Time: 13.38 ms, Memory: 87.9 MB -BaekjoonHub
1 parent 1ef5ead commit bced1a0

2 files changed

Lines changed: 305 additions & 0 deletions

File tree

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
# [level 3] 디스크 컨트롤러 - 42627
2+
3+
[문제 링크](https://school.programmers.co.kr/learn/courses/30/lessons/42627?language=java)
4+
5+
### 성능 요약
6+
7+
메모리: 87.9 MB, 시간: 13.38 ms
8+
9+
### 구분
10+
11+
코딩테스트 연습 > 힙(Heap)
12+
13+
### 채점결과
14+
15+
정확성: 100.0<br/>합계: 100.0 / 100.0
16+
17+
### 제출 일자
18+
19+
2026년 09월 04일 14:52:28
20+
21+
### 문제 설명
22+
23+
<p>하드디스크는 한 번에 하나의 작업만 수행할 수 있습니다. 디스크 컨트롤러를 구현하는 방법은 여러 가지가 있습니다. 이 문제에서는 <strong>우선순위 디스크 컨트롤러</strong>라는 가상의 장치를 이용한다고 가정합니다. <strong>우선순위 디스크 컨트롤러</strong>는 다음과 같이 동작합니다.</p>
24+
25+
<ol>
26+
<li>어떤 작업 요청이 들어왔을 때 작업의 번호, 작업의 요청 시각, 작업의 소요 시간을 저장해 두는 <strong>대기 큐</strong>가 있습니다. 처음에 이 큐는 비어있습니다.</li>
27+
<li>디스크 컨트롤러는 하드디스크가 작업을 하고 있지 않고 <strong>대기 큐</strong>가 비어있지 않다면 가장 우선순위가 높은 작업을 <strong>대기 큐</strong>에서 꺼내서 하드디스크에 그 작업을 시킵니다. 이때, 작업의 소요시간이 짧은 것, 작업의 요청 시각이 빠른 것, 작업의 번호가 작은 것 순으로 우선순위가 높습니다.</li>
28+
<li>하드디스크는 작업을 한 번 시작하면 작업을 마칠 때까지 그 작업만 수행합니다.</li>
29+
<li>하드디스크가 어떤 작업을 마치는 시점과 다른 작업 요청이 들어오는 시점이 겹친다면 하드디스크가 작업을 마치자마자 디스크 컨트롤러는 요청이 들어온 작업을 <strong>대기 큐</strong>에 저장한 뒤 우선순위가 높은 작업을 <strong>대기 큐</strong>에서 꺼내서 하드디스크에 그 작업을 시킵니다. 또, 하드디스크가 어떤 작업을 마치는 시점에 다른 작업이 들어오지 않더라도 그 작업을 마치자마자 또 다른 작업을 시작할 수 있습니다. 이 과정에서 걸리는 시간은 없다고 가정합니다.</li>
30+
</ol>
31+
32+
<p>예를 들어</p>
33+
<div class="highlight"><pre class="codehilite"><code>- 0ms 시점에 3ms가 소요되는 0번 작업 요청
34+
- 1ms 시점에 9ms가 소요되는 1번 작업 요청
35+
- 3ms 시점에 5ms가 소요되는 2번 작업 요청
36+
</code></pre></div>
37+
<p>와 같은 요청이 들어왔습니다. 이를 그림으로 표현하면 다음과 같습니다.</p>
38+
39+
<p><img src="https://asset.programmers.co.kr/files/production/02c70993-ca43-4130-ac63-0dec59e091c6/image.001.jpeg" title="" alt="image.001.jpeg"></p>
40+
41+
<p>이 요청을 <strong>우선순위 디스크 컨트롤러</strong>가 처리하는 과정은 다음 표와 같습니다.</p>
42+
<table class="table">
43+
<thead><tr>
44+
<th>시점</th>
45+
<th>하드디스크</th>
46+
<th>대기 큐</th>
47+
<th>디스크 컨트롤러</th>
48+
</tr>
49+
</thead>
50+
<tbody><tr>
51+
<td>0ms</td>
52+
<td></td>
53+
<td>[]</td>
54+
<td></td>
55+
</tr>
56+
<tr>
57+
<td>0ms</td>
58+
<td></td>
59+
<td>[[0번, 0ms, 3ms]]</td>
60+
<td>0번 작업 요청을 대기 큐에 저장</td>
61+
</tr>
62+
<tr>
63+
<td>0ms</td>
64+
<td>0번 작업 시작</td>
65+
<td>[]</td>
66+
<td>대기 큐에서 우선순위가 높은 0번 작업을 꺼내서 작업을 시킴</td>
67+
</tr>
68+
<tr>
69+
<td>1ms</td>
70+
<td>0번 작업 중</td>
71+
<td>[[1번, 1ms, 9ms]]</td>
72+
<td>1번 작업 요청을 대기 큐에 저장</td>
73+
</tr>
74+
<tr>
75+
<td>3ms</td>
76+
<td>0번 작업 완료</td>
77+
<td>[[1번, 1ms, 9ms]]</td>
78+
<td></td>
79+
</tr>
80+
<tr>
81+
<td>3ms</td>
82+
<td></td>
83+
<td>[[1번, 1ms, 9ms], [2번, 3ms, 5ms]]</td>
84+
<td>2번 작업 요청을 대기 큐에 저장</td>
85+
</tr>
86+
<tr>
87+
<td>3ms</td>
88+
<td>2번 작업 시작</td>
89+
<td>[[1번, 1ms, 9ms]]</td>
90+
<td>대기 큐에서 우선순위가 높은 2번 작업을 꺼내서 작업을 시킴</td>
91+
</tr>
92+
<tr>
93+
<td>8ms</td>
94+
<td>2번 작업 완료</td>
95+
<td>[[1번, 1ms, 9ms]]</td>
96+
<td></td>
97+
</tr>
98+
<tr>
99+
<td>8ms</td>
100+
<td>1번 작업 시작</td>
101+
<td>[]</td>
102+
<td>대기 큐에서 우선순위가 높은 1번 작업을 꺼내서 작업을 시킴</td>
103+
</tr>
104+
<tr>
105+
<td>17ms</td>
106+
<td>1번 작업 완료</td>
107+
<td>[]</td>
108+
<td></td>
109+
</tr>
110+
</tbody>
111+
</table>
112+
<p>모든 요청 작업을 마쳤을 때 각 작업에 대한 <strong>반환 시간(turnaround time)</strong>은 작업 요청부터 종료까지 걸린 시간으로 정의합니다. 위의 <strong>우선순위 디스크 컨트롤러</strong>가 처리한 각 작업의 <strong>반환 시간</strong>은 다음 그림, 표와 같습니다.</p>
113+
114+
<p><img src="https://asset.programmers.co.kr/files/production/fdfb33a3-1ad4-443a-a5d0-09b3dc548ece/image.002.jpeg" title="" alt="image.002.jpeg"></p>
115+
<table class="table">
116+
<thead><tr>
117+
<th>작업 번호</th>
118+
<th>요청 시각</th>
119+
<th>작업 종료 시각</th>
120+
<th>반환 시간</th>
121+
</tr>
122+
</thead>
123+
<tbody><tr>
124+
<td>0번</td>
125+
<td>0ms</td>
126+
<td>3ms</td>
127+
<td>3ms(= 3ms - 0ms)</td>
128+
</tr>
129+
<tr>
130+
<td>1번</td>
131+
<td>1ms</td>
132+
<td>17ms</td>
133+
<td>16ms(= 17ms - 1ms)</td>
134+
</tr>
135+
<tr>
136+
<td>2번</td>
137+
<td>3ms</td>
138+
<td>8ms</td>
139+
<td>5ms(= 8ms - 3ms)</td>
140+
</tr>
141+
</tbody>
142+
</table>
143+
<p><strong>우선순위 디스크 컨트롤러</strong>에서 모든 요청 작업의 반환 시간의 평균은 8ms(= (3ms + 16ms + 5ms) / 3)가 됩니다.</p>
144+
145+
<p>각 작업에 대해 [작업이 요청되는 시점, 작업의 소요시간]을 담은 2차원 정수 배열 <code>jobs</code>가 매개변수로 주어질 때, <strong>우선순위 디스크 컨트롤러</strong>가 이 작업을 처리했을 때 모든 요청 작업의 반환 시간의 평균의 정수부분을 return 하는 solution 함수를 작성해 주세요.</p>
146+
147+
<hr>
148+
149+
<h5>제한 사항</h5>
150+
151+
<ul>
152+
<li>1 ≤ <code>jobs</code>의 길이 ≤ 500 </li>
153+
<li><code>jobs[i]</code>는 <code>i</code>번 작업에 대한 정보이고 [s, l] 형태입니다.
154+
155+
<ul>
156+
<li>s는 작업이 요청되는 시점이며 0 ≤ s ≤ 1,000입니다.</li>
157+
<li>l은 작업의 소요시간이며 1 ≤ l ≤ 1,000입니다.</li>
158+
</ul></li>
159+
</ul>
160+
161+
<hr>
162+
163+
<h5>입출력 예</h5>
164+
<table class="table">
165+
<thead><tr>
166+
<th>jobs</th>
167+
<th>return</th>
168+
</tr>
169+
</thead>
170+
<tbody><tr>
171+
<td>[[0, 3], [1, 9], [3, 5]]</td>
172+
<td>8</td>
173+
</tr>
174+
</tbody>
175+
</table>
176+
<hr>
177+
178+
<h5>입출력 예 설명</h5>
179+
180+
<p>입출력 예 #1</p>
181+
182+
<ul>
183+
<li>문제에 주어진 예와 같습니다.</li>
184+
</ul>
185+
186+
<hr>
187+
188+
<h5>문제가 잘 안풀린다면😢</h5>
189+
190+
<p>힌트가 필요한가요? [코딩테스트 연습 힌트 모음집]으로 오세요! → <a href="https://school.programmers.co.kr/learn/courses/14743?itm_content=lesson42627" target="_blank" rel="noopener">클릭</a></p>
191+
192+
<hr>
193+
194+
<p>※ 공지 - 2024년 11월 14일 문제 지문이 리뉴얼되었습니다. 기존에 제출한 코드가 통과하지 못할 수도 있습니다.</p>
195+
196+
197+
> 출처: 프로그래머스 코딩 테스트 연습, https://school.programmers.co.kr/learn/challenges
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import java.util.*;
2+
3+
class Solution {
4+
5+
class Job{
6+
private int idx; //작업번호
7+
private int s; // 작업 요청 시점
8+
private int l; // 작업 소요 시간
9+
10+
Job(int idx, int s, int l){
11+
this.idx = idx;
12+
this.s = s;
13+
this.l = l;
14+
}
15+
16+
Job(int[] job){
17+
this.idx = job[0];
18+
this.s = job[1];
19+
this.l = job[2];
20+
}
21+
}
22+
23+
24+
public int solution(int[][] jobs) {
25+
int answer = 0;
26+
27+
// 작업 시작 시점에서 대기 큐 검사 : 작업의 소요시간 l 이 짧은 것, 작업의 요청 시각 s 이 빠른 것, 작업의 번호 idx가 작은 것 순
28+
29+
// jobs[i]는 i번 작업에 대한 정보이고 [s(작업요청시점), l(작업 소요시간)] 형태
30+
31+
List<int[]> jobList = new ArrayList<>();
32+
33+
for(int i= 0; i<jobs.length; i++){
34+
jobList.add(new int[]{i, jobs[i][0], jobs[i][1]});
35+
}
36+
jobList.sort((a, b) -> a[1] - b[1]);
37+
38+
int time = 0;
39+
int idx = 0;
40+
int endTime = 0;
41+
int count = 0;
42+
43+
// 대기 큐
44+
PriorityQueue<Job> pq = new PriorityQueue<Job>( (j1, j2)->{
45+
if(j1.l == j2.l){
46+
if(j1.s == j2.s){
47+
return j1.idx - j2.idx;
48+
}
49+
else return j1.s - j2.s;
50+
}
51+
return j1.l - j2.l;
52+
53+
});
54+
55+
// 작업 큐
56+
Queue<Job> q = new LinkedList<>();
57+
58+
59+
while(count < jobs.length){
60+
61+
// 1. 현재 시간(time) 이하에 요청된 작업들을 대기 큐 삽입
62+
while(idx < jobs.length){
63+
int[] job = jobList.get(idx);
64+
if(job[1] <= time){
65+
pq.add(new Job(job));
66+
idx++;
67+
}
68+
else break;
69+
}
70+
71+
72+
// 2. 현재 진행 중이던 작업이 끝나는 시점이라면
73+
if(endTime == time){
74+
// 직전까지 실행 중이던 작업 처리 완료
75+
if(!q.isEmpty()){
76+
Job curJob = q.poll();
77+
answer += (time - curJob.s);
78+
// System.out.println(time-curJob.s);
79+
count++;
80+
}
81+
// + 대기큐에서 꺼내고 endTime update
82+
if(!pq.isEmpty()){
83+
Job nextJob = pq.poll();
84+
q.add(nextJob);
85+
endTime = time + nextJob.l;
86+
}
87+
}
88+
89+
if(q.isEmpty() && !pq.isEmpty()){
90+
Job nextJob = pq.poll();
91+
q.add(nextJob);
92+
endTime = time + nextJob.l;
93+
}
94+
95+
if(q.isEmpty() && pq.isEmpty() && idx<jobs.length){
96+
time = jobList.get(idx)[1];
97+
continue;
98+
}
99+
100+
time++;
101+
102+
}
103+
104+
105+
// 모든 요청 작업의 반환 시간의 평균의 정수부분을 return
106+
return answer/jobs.length;
107+
}
108+
}

0 commit comments

Comments
 (0)