항해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
'알고리즘 > 항해99 스터디' 카테고리의 다른 글
99클럽 코테 스터디 7일차 TIL - 정렬 (0) | 2024.05.26 |
---|---|
99클럽 코테 스터디 6일차 TIL - 우선순위큐 (0) | 2024.05.25 |
99클럽 코테 스터디 4일차 TIL - 스택 (0) | 2024.05.23 |
99클럽 코테 스터디 3일차 TIL - 스택/큐 (0) | 2024.05.22 |
99클럽 코테 스터디 2일차 TIL - 문자열, 해시 (0) | 2024.05.21 |
댓글