본문 바로가기
알고리즘/항해99 스터디

99클럽 코테 스터디 5일차 TIL - 우선순위큐

2024. 5. 24.

항해99 코테 스터디 5일차 문제인 프로그래머스의 '디스크 컨트롤러'는 한번에 하나의 작업만 수행할 수 있는 하드디스크에 요청들이 들어왔을 때 모든 요청의 대기시간의 평균의 최솟값을 구하는 문제다. 난이도는 레벨3이며 우선순위큐를 통해 해결할 수 있다.

 

오늘의 문제 - 디스크 컨트롤러 문제 정보

문제 키워드

- 힙/우선순위큐

난이도

- Level 3

 

문제 요약

  • 하드디스크는 한번에 하나의 작업만 해결할 수 있다.
  • 작업 요청이 들어온 시간과 해당 작업을 수행하는데 걸리는 시간이 배열로 주어질 때, 모든 요청이 끝나고 각 요청의 평균 대기시간의 최소값을 구하라.

 

문제 풀이 과정  

  • 디스크 스케줄링 기법은 선입 우선, 최소시간 우선 등이 있다. 이 문제에서는 각 작업이 끝날 때까지 기다린 대기시간이 최소화되어야 하므로, 최소시간 우선 기법을 사용할 것이다.
    • 따라서 우선순위큐를 이용해 삽입된 작업을 작업시간 오름차순으로 정렬되도록 하였다.
  • 매 시간마다 현재 진행 중인 작업이 있는지 확인하고, 작업이 있다면 작업이 끝났는지 확인 후 종료시킨다.
  • 현재 진행 중인 작업이 없다면 요청된 작업 중 가장 적게 걸리는 작업을 시작한다.
  • 최종적으로 각 작업의 대기시간의 총합을 작업의 개수로 나누어 평균 시간을 반환하였다.
  • 메인함수 구현의 편의성을 위해 Task라는 클래스를 만들고 편의성 함수들을 구현해놓았다.
    • 현재 시간에 작업이 끝났는지 확인하는 함수, 작업 대기시간을 구하는 함수 등

코드

import java.util.*;
class Solution {
public int solution(int[][] jobs) {
int N = jobs.length;
// 작업 목록을 요청 시간별로 map으로 묶음
Map<Integer, List<Integer>> jobTimeMap = new HashMap<>();
for(int[] job: jobs) {
int enterT = job[0], jobT = job[1];
jobTimeMap.putIfAbsent(enterT, new ArrayList<>());
jobTimeMap.get(enterT).add(jobT);
}
// 시간의 흐름에 따라 작업 요청, 작업 시작 및 종료 확인
int t = 0, timeSum = 0, restJob = N;
Task nowTask = null;
PriorityQueue<Task> tasks = new PriorityQueue<>();
while (restJob > 0) {
// 현재 시간에 요청된 작업을 pq에 삽입
if (jobTimeMap.containsKey(t)) {
for(int jobT : jobTimeMap.get(t)) {
tasks.add(new Task(t, jobT));
}
}
// 현재 작업이 끝났는지 확인
if (nowTask != null && nowTask.isJobDone(t)){
timeSum += nowTask.getWaitTime();
restJob--;
nowTask = null;
}
// 현재 진행중인 작업이 없으면 가능한 작업 중
// 작업 시간이 가장 짧은걸로 시작
if (nowTask == null && !tasks.isEmpty()) {
nowTask = tasks.poll();
nowTask.setStartT(t);
}
t++;
}
return (int) timeSum / N;
}
class Task implements Comparable<Task> {
int enterTime;
int jobTime;
int startTime;
public Task (int enterTime, int jobTime) {
this.enterTime = enterTime;
this.jobTime = jobTime;
}
public void setStartT(int t) {
this.startTime = t;
}
public boolean isJobDone(int nowT) {
return nowT - startTime >= jobTime;
}
public int getWaitTime() {
return startTime + jobTime - enterTime;
}
@Override
public int compareTo(Task other) {
if (this.jobTime == other.jobTime) {
return this.enterTime - other.enterTime;
}
return this.jobTime - other.jobTime;
}
}
}
  • 시간복잡도: O(N*T) → T: 최대 작업시간
  • 공간복잡도: O(N)

 

오늘의 학습 회고

새롭게 알게된 것

  • 오래전에 C++로 코딩테스트를 준비하던 시절에 풀었던 문제인데, 자바로 다시 푸니 새로웠다.
    • 새삼, c++보다 자바가 훨씬 편하고 가독성도 좋다는 생각이 들었다. 자바짱ㅎㅎ
  • 이렇게 시간 기준으로 푼 문제는 시간복잡도를 계산하기가 어렵다ㅠㅠ
728x90

댓글