본문 바로가기
알고리즘 문제풀이

[프로그래머스] 디스크 컨트롤러 (Java)

by SiO2whocode 2025. 6. 26.

https://school.programmers.co.kr/learn/courses/30/lessons/42627?language=java

 

프로그래머스

SW개발자를 위한 평가, 교육의 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr

 

시뮬레이션

 

작업번호 = 인덱스, 요청시간, 소요시간 을 가진 작업들이 N개 주어지고

이를 소요시간 짧은순, 요청시간 이른 순, 작업 번호 작은순으로 실행하여

각 작업 마다 완료 시각 - 요청시각을 뺀 값을 구해서 평균을 반환하는 문제

 

접근방법

1. 요청시간이 이른 순으로 작업들을 정렬한다.

2. 문제의 우선순위를 반영한 우선순위큐를 선언한다.

3. 요청시간이 이른 순으로 정렬된 작업들을 앞에서 부터 보면서 현재 시각 t와 요청시각이 일치한 작업들은 우선순위 큐에 삽입한다.

4. 현재 작업 중인 작업이 종료되었거나 없을 경우 우선순위큐에서 poll하여 현재 작업으로 시작한다.

5. 매번 반복문 마다 (1초 소요) 현재 작업 중인 작업의 시간을 1초 줄이고 (시간이 흘렀으니까), 0일 경우 현재 작업에서 삭제하고, 반환 시각을 구하여 turns에 추가한다.

6. turns에 모든 작업들이 계산되었으면 모두 더하여 평균값을 구한다.

 

소소코드

하 일단 여전히 배열 -> 리스트, 리스트 -> 배열이 약한데, 이번엔 이차원리스트라 더 헷갈렸다.

그래서 걍 빈 리스트 만들고 add하는게 편함.

리스트는 .sort 메서드가 있고, array는 Arrays.sort로 써야한다아아ㅏ

리스트는 인덱스 참조도 get으로 해야하는데 또 까먹음

작업들을 우선순위큐로 옮겨야해서 작업들 리스트를 큐로 선언했으면 좋으련만,,

그냥 시작 인덱스를 옮겨가는 식으로 구현했다.

turns forEach에서 지역변수 sum 바꾸는거 안되더라. 응 함수형 프로그래밍이라^_^ reduce같은걸 쓰면 되겠지만..스위프트에서 밖에 안쓰다보니까 또 까먹음^_^

import java.util.*;

class Solution {
    
    class Task implements Comparable<Task> {
        int time = 0;
        int request = 0;
        int number = 0;
        
        Task (int time, int request, int number) {
            this.time = time;
            this.request = request;
            this.number = number;
        }
        
        public int compareTo(Task other) {
            if(this.time != other.time) { return this.time - other.time; }
            if(this.request != other.request) { return this.request - other.request; }
            return this.number - other.number;
        }
    }
    
    public int solution(int[][] jobs) {
        int answer = 0;
        // jobs 배열 -> List
        List<List<Integer>> njobs = new ArrayList<>();
        for(int i = 0 ; i < jobs.length ; i++) {
            List<Integer> aa = new ArrayList<>();
            aa.add(jobs[i][1]);
            aa.add(jobs[i][0]);
            aa.add(i);
            njobs.add(aa);
        }
        // 요청시간 순으로 정렬
        njobs.sort((a,b) -> {
            return a.get(1) - b.get(1);
        });
        
        // 대기 큐 만들기 (우선순위 반영)
        PriorityQueue<Task> pq = new PriorityQueue<>();
        
        int jobStartIdx = 0;
        int n = jobs.length;
        
        Task now = null;
        int remain = 0;
        
        List<Integer> turns = new ArrayList<>();
        
        int t = 0;
        while(turns.size() < n) {
            // 작업들 중 t에 요청 들어온 작업 pq에 넣기
            int last = jobStartIdx;
            for(int i = jobStartIdx; i < n ; i++) {
                if(njobs.get(i).get(1) == t) {
                    last = i+1;
                    pq.offer(new Task(njobs.get(i).get(0), njobs.get(i).get(1), njobs.get(i).get(2)));
                } else {
                    break;
                }
            }
            jobStartIdx = last;
            
            // 현재 작업 종료 여부 판단
            if(remain == 0) {
                if(now != null) {
                    // 수행하던 작업이 끝난 거면 반환 시간 계산해서 turns에 추가
                    turns.add(t - now.request);
                    now = null;
                }
                // 새로운 작업 시작
                now = pq.poll();
                if(now != null) {
                    remain = now.time;
                }
            }
            
            // 작업 수행
            if(now != null) {            
               remain--;
            }
            t++;
        }

        int sum = 0 ;
        for(Integer a : turns) {
            sum = sum + a;
        }
        answer = sum / n;
        return answer;
    }
}

 

728x90