프로그래머스 - 힙 - 디스크 컨트롤러

2021. 3. 22. 17:07Algorithm

programmers.co.kr/learn/courses/30/lessons/42627

 

코딩테스트 연습 - 디스크 컨트롤러

하드디스크는 한 번에 하나의 작업만 수행할 수 있습니다. 디스크 컨트롤러를 구현하는 방법은 여러 가지가 있습니다. 가장 일반적인 방법은 요청이 들어온 순서대로 처리하는 것입니다. 예를

programmers.co.kr

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
import java.util.Arrays;
import java.util.PriorityQueue;
import java.util.Queue;
 
public class 디스크_컨트롤러 {
    public static void main(String[] args) {
        디스크_컨트롤러 o = new 디스크_컨트롤러();
        System.out.println(o.solution(new int[][]{{01}, {43}}));
    }
 
    public int solution(int[][] jobs) {
        HardDisk hardDisk = new HardDisk(jobs);
        return hardDisk.process();
    }
 
    class HardDisk {
        private int[][] jobs;
        Queue<int[]> q = new PriorityQueue<int[]>((o1, o2) -> {
            int ret = o1[1- o2[1];
            if(ret == 0) {
                ret = o1[0- o2[0];
            }
            return ret;
        });
 
        public HardDisk(int[][] jobs) {
            this.jobs = jobs;
            init();
        }
 
        public void init() {
            Arrays.sort(jobs, (o1, o2) -> o1[0- o2[0]);
        }
 
        public int process() {
            int lastJobIndex = -1;
            int totalJobEndTime = jobs[0][0];
            int sumTaskTime = 0;
 
            while (!q.isEmpty() || lastJobIndex < jobs.length) {
                if(!q.isEmpty()) {
                    int[] curJob = q.poll();
                    int taskTime = 0;
 
                    if(curJob[0< totalJobEndTime) {
                        totalJobEndTime += curJob[1];
                        taskTime = totalJobEndTime - curJob[0];
                    } else {
                        taskTime = curJob[1];
                        totalJobEndTime += curJob[1];
                    }
 
                    sumTaskTime += taskTime;
                }
                lastJobIndex = registerJob(lastJobIndex, totalJobEndTime);
            }
 
            return sumTaskTime / jobs.length;
        }
 
        private int registerJob(int lastJobIndex, int totalJobEndTime) {
            lastJobIndex++;
            int count = 0;
            for(int i = lastJobIndex; i<jobs.length; i++) {
                if(totalJobEndTime >= jobs[i][0]) {
                    q.offer(jobs[i]);
                    lastJobIndex = i;
                    count++;
                } else {
                    break;
                }
            }
            if(count == 0 && lastJobIndex < jobs.length) {
                q.offer(jobs[lastJobIndex]);
            }
 
            return lastJobIndex;
        }
    }
}
 
cs

 

알고리즘

  • 굉장히 복잡하게 푼 느낌이다.. 이것 저것 고려해야할것이 많았다
  • 힙을 이용해서 매순간 동적으로 우선순위를 정하면 된다.
  • 알고리즘에 대해 설명하면
  1. 작업들을 요청 순서대로 정렬.
  2. 첫번째 작업과 같은 요청시간대의 작업들을 모두 큐에 넣는다. 리스트의 마지막 작업 인덱스를 기록해둔다(수행됐던 작업의 중복을 막기 위해)
  3. 큐에서 하나의 작업을 빼서 작업을 진행한다.
  4. 작업이 끝난 시간을 알아내고 그 시간 전에 요청한 작업이 있다면(마지막 작업 인덱스 이후의 작업 중에) 큐에 작업들을 넣는다. 작업이 끝난 시간 전에 요청한 작업이 없고 다음 작업이 남아 있다면 해당 작업을 큐에 넣는다.
  5. 큐에 작업이 없고 마지막 작업 인덱스가 작업 리스트의 크기와 같다면 작업 종료. 작업이 끝난 최종시간과 작업 리스트의 크기를 나누어 리턴.