-
프로그래머스 문제 풀이 디스크 컨트롤러24년 11월 이전/레거시-프로그래머스-코딩 테스트 고득점 kit 2019. 12. 4. 23:37반응형
문제 URL 디스크 컨트롤러
Contents
- 문제 지문 파악하기
- 구르미의 알고리즘 풀이
문제 지문 파악하기
이번에도, 입력을 통해서 문제를 파악해보도록 하겠습니다. 문제의 입력은 이렇습니다.
입력:
jobs = [[0, 3], [1, 9], [2, 6]]이 때, 먼저 최초 작업은 request=0, expend=3인 작업을 진행합니다. 그러면 결국 이렇게 됩니다.
jobs = [[1, 9], [2, 6]]
n = 1 //처리한 작업의 개수
time = 3 //현재 시간 (0 + expend=3)
answer = 3 // 작업 요청부터 작업이 마무리까지 걸린 시간 (0 + expend)이제 어떤 작업을 골라야 할까요? 이럴 경우, 요청 시간이 짧은 걸 먼저 처리할수록, answer에 크기가 작아집니다. 즉, request=2, expend=6인 작업을 처리합니다.
jobs = [[1, 9]]
n = 2 //처리한 작업의 개수
time = 9 //현재 시간 (time = 3 + expend = 6)
answer = 10 // 작업 요청부터 작업이 마무리까지 걸린 시간 (answer = 3 + time = 9 - request = 2)이제 마지막 작업을 처리합니다.
jobs = []
n = 3 //처리한 작업의 개수
time = 18 //현재 시간
answer = 27 // 작업 요청부터 작업이 마무리까지 걸린 시간 (answer = 10 + time = 18 - request = 1)그래서 이들의 평균을 구하면 됩니다.
answer = 9 (answer = 27 / n = 3)
이번엔 다른 예제를 살펴볼까요? 다음 입력이 들어왔다고 가정합시다.
입력:
jobs = [[1, 9], [2, 15], [10, 1]]그럼 이젠 request=1, expend=9인 작업을 처리하죠?
jobs = [[2, 6], [10, 1]]
n = 1 //처리한 작업의 개수
time = 10 //현재 시간 (time = request = 1 + expend = 9)
answer = 9 (0 + time = 10 - request = 1)이제 2가지 중 어떤 걸 처리해야 할까요? 이 때는 현재 시간 기준으로 이미 들어온 입력들이 우선순위를 가집니다. 즉 request=2, expend=6인 작업을 처리해야 합니다.
jobs = [[10, 1]]
n = 2 //처리한 작업의 개수
time = 16 // time = 10 + expned = 6
answeer = 23 // answer = 9 + time = 16 - request =2이제 request = 10, expend = 1 인 작업을 처리합니다.
jobs = []
n = 3 //처리한 작업의 개수
time = 17 // time = 16 + expned = 1
answeer = 30 // answer = 23 + time = 17 - request = 10여기서 나눈 몫을 구하면 답은 다음과 같습니다.
answer = 10 // answer = 30 / n = 3
어떻게 풀 수 있을까요? 먼저 이 문제는 파트 "힙"에서 알 수 있듯이 우선 순위 큐를 써야 합니다. 제가 세운 알고리즘은 다음과 같습니다. 우선, 입력은 첫 번째 입력으로 하겠습니다.
입력:
jobs = [[0, 3], [1, 9], [2, 6]]먼저, jobs를 정렬시키고, time의 최초 시간을, jobs의 첫 원소의 요청 시간으로 설정합니다. (두 번째 경우를 위해서입니다.)
jobs = [[0, 3], [1, 9], [2, 6]]
time = 0그리고 우선순위 큐를 하나 생성해둡니다.
jobs = [[0, 3], [1, 9], [2, 6]]
time = 0
pq = []이제 작업들을 처리해봅시다. 먼저 첫 원소를 빼줍니다. 이때, 개수를 세워줍니다.
jobs = [[1, 9], [2, 6]]
(request, expend) = [0, 3]
n = 1
time = 0
pq = []위에서 손으로 풀어보았을 때, 결국 time은 작업 처리할 때 다음 수식을 만족합니다.
time += expend
또한, answer는 다음 수식을 만족합니다.
answer += (time - request)
이제 작업을 처리한 시간들을 계산해줍시다.
jobs = [[1, 9], [2, 6]]
(request, expend) = [0, 3]
n = 1
time = 3
answer = 3
pq = []그리고 현재 시간 time보다 작은 request를 가진 작업이 jobs에 있다면, 모두 뺴내 pq에 저장합니다. 대신, 이 pq는 expend 기준으로 최대 힙인 우선순위 큐로 합니다.
이때는 time=3이므로, [1, 9], [2, 6] 모두 뺴져 pq로 들어가게 됩니다. 들어갈 때, expend 기준으로 들어가야 합니다! 즉 이렇게 될 것입니다.
jobs = []
(request, expend) = [0, 3]
n = 1
time = 3
answer = 3
pq = [[9, 1], [6, 2]] //expend 기준이제 우선순위 큐 pq가 빌 떄까지 다시 원소를 꺼내어, jobs에 머리에 넣습니다. 즉, pq에서 우선순위가 가장 낮은 원소가 결국은 다음에 빠져나가야할 원소인 것입니다.
//pq 처음 뺴낼 때
jobs = [[2, 6]]
(request, expend) = [0, 3]
n = 1
time = 3
answer = 3
pq = [[9, 1]]
//pq 처음 뺴낼 때
jobs = [[2, 6], [1, 9]]
(request, expend) = [0, 3]
n = 1
time = 3
answer = 3
pq = []이제, 위의 과정을 반복합니다. 각 과정을 반복했을 때, 나타나는 결과는 다음과 같습니다. 한 번 손으로 직접 풀어보세요!
n = 2
jobs = [[1, 9]]
time = 9
answer = 10
n = 3
jobs = []
time = 18
answer = 27jobs가 이제 비게 되면, answer를 n으로 나눈 몫을 답으로 반환하면 됩니다. 즉 이 문제에서 답은 9입니다.
구르미의 알고리즘 풀이
"문제 지문 파악하기"를 토대로 세운 알고리즘을 순서대로 나열하면 다음과 같습니다.
- jobs를 정렬합니다.
- 최초 시간 time을 정렬된 jobs[0][0]로 합니다.
- 우선순위 큐 pq를 생성합니다. 이 때 (expend, request)를 원소로 합니다.
- jobs가 빌 때까지 다음을 반복합니다.
- jobs의 첫 원소를 꺼내옵니다.
- n에 1을 더해줍니다.
- time에 꺼내온 원소의 소요 시간 expend을 더해줍니다.
- answer에 time에 꺼내온 원소의 요청 시간 request를 뺀 시간을 더해줍니다.
- jobs가 비지 않고 jobs[0][0]가 time 보다 작을 때, 다음을 반복합니다.
- jobs에서 원소를 꺼내옵니다.
- 우선순위 큐 pq에 소요 시간 기준 Max 힙으로 원소를 저장합니다.
- 우선순위 큐 pq가 빌 때까지 다음을 반복합니다.
- pq에서 원소를 꺼내옵니다.
- 그 원소를 다시 jobs 첫 원소로 집어넣습니다.
- answer에 n을 나눈 몫을 저장하고 반환합니다.
이를 코드로 표현하면 다음과 같습니다.
PYTHON 코드
def solution(jobs): import heapq # 1. jobs 정렬 jobs.sort() answer = 0 n = 0 # 2. 최초 시간 설정 time = jobs[0][0] # 3. 우선순위 큐 생성 pq = [] # 4. job이 빌 떄까지 다음을 반복합니다. while jobs: # 1. jobs의 첫 원소를 꺼내옵니다. (request, expend) = jobs.pop(0) # 2. n에 1을 더해줍니다. n += 1 # 3. time에 소요 시간 expend를 더해줍니다. time += expend # 4. answer에 현재 시간 time에서 요청 시간 request를 뺸 값을 더해줍니다. answer += (time - request) # 5. jobs가 비지 않고, jobs[0][0]일 떄 다음을 반복합니다. while jobs and jobs[0][0] < time: # 1. jobs의 첫 원소를 꺼내옵니다. (request, expend) = jobs.pop(0) # 2. 해당 원소를 expend 기준으로 pq에다 저장합니다. heapq.heappush(pq, (-expend, request)) # 6. pq가 빌 떄까지 다음을 반복합니다. while pq: # 1. pq에서 원소를 꺼냅니다. (expend, request) = heapq.heappop(pq) # 2. jobs에 첫 원소로 저장합니다. jobs.insert(0, [request, -expend]) # 5. answer에 n을 나눠준 몫을 저장하고 반환합니다. answer //= n return answer
이번엔 CPP 코드입니다. 언어만 바뀐 것이지 알고리즘은 같습니다.
CPP 코드
#include <string> #include <vector> #include <queue> #include <algorithm> using namespace std; int solution(vector<vector<int>> jobs) { sort(jobs.begin(), jobs.end()); int answer = 0; int n = 0; int time = jobs[0][0]; priority_queue<pair<int, int>, vector<pair<int, int>>, less<pair<int, int>>> pq; while (!jobs.empty()) { auto job = jobs[0]; jobs.erase(jobs.begin()); n += 1; time += job[1]; answer += (time - job[0]); while (!jobs.empty() && jobs[0][0] < time) { auto job = jobs[0]; jobs.erase(jobs.begin()); pq.push(make_pair(job[1], job[0])); } while (!pq.empty()) { auto job = pq.top(); jobs.insert(jobs.begin(), vector<int>{ job.second, job.first }); pq.pop(); } } answer /= n; return answer; }
728x90'레거시 > 레거시-프로그래머스-코딩 테스트 고득점 kit' 카테고리의 다른 글
프로그래머스 문제 풀이 K번째 수 (0) 2019.12.06 프로그래머스 문제 풀이 이중 우선순위 큐 (1) 2019.12.05 프로그래머스 문제 풀이 라면 공장 (0) 2019.12.02 프로그래머스 문제 풀이 쇠막대기 (0) 2019.11.30 프로그래머스 문제 풀이 주식 가격 (9) 2019.11.30