본문 바로가기
스터디IT🌼/Algorithm

[ 프로그래머스 ] 디스크 컨트롤러 _ Heap

by 동백사과 2022. 9. 30.

[ 문제 분류 ]

- Heap 

더보기

! Heap !

- 힙은 완전이진트리의 형태로 만들어진 자료구조 

 

[ 힙의 종류 ]

- 최소 힙 ( min heap ) : 부모노드 < 자식 노드

- 최대 힙 ( max heap ) : 부모 노드 > 자식 노드 

 

[ 힙의 활용 ]

- 최댓값 혹은 최솟값을 빠르게 찾아내기 유리한 자료 구조!

- 우선순위 큐를 구현할 때 스이기도 하고 허프만 코드를 구현할때도 쓰임

 [ 파이썬 heapq heap ]

  • -파이썬 heapq 모듈은 최소힙을 기본으로 제공 ( 값에 음수를 붙여 최대 힙도 구현 가능 )
  • heapq.heappush(heap, item) : item을 heap에 추가
  • heapq.heappop(heap) : heap에서 가장 작은 원소를 pop & 리턴. 비어 있는 경우 IndexError가 호출됨. 
  • heapq.heapify(x) : 리스트 x를 즉각적으로 heap으로 변환함 (in linear time, O(N) )

 

[ 문제 링크 ]

- https://school.programmers.co.kr/learn/courses/30/lessons/42627

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

[ 문제 설명 ]

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

예를들어

- 0ms 시점에 3ms가 소요되는 A작업 요청
- 1ms 시점에 9ms가 소요되는 B작업 요청
- 2ms 시점에 6ms가 소요되는 C작업 요청

와 같은 요청이 들어왔습니다. 이를 그림으로 표현하면 아래와 같습니다.

한 번에 하나의 요청만을 수행할 수 있기 때문에 각각의 작업을 요청 받은 순서대로 처리하면 다음과 같이 처리 됩니다. 

- A: 3ms 시점에 작업 완료 (요청에서 종료까지 : 3ms)
- B: 1ms부터 대기하다가, 3ms 시점에 작업을 시작해서 12ms 시점에 작업 완료(요청에서 종료까지 : 11ms)
- C: 2ms부터 대기하다가, 12ms 시점에 작업을 시작해서 18ms 시점에 작업 완료(요청에서 종료까지 : 16ms)

이 때 각 작업의 요청부터 종료까지 걸린 시간의 평균은 10ms(= (3 + 11 + 16) / 3)가 됩니다.

하지만 A → C→ B 순서대로 처리하면

- A: 3ms 시점에 작업 완료(요청에서 종료까지 : 3ms)
- C: 2ms부터 대기하다가, 3ms 시점에 작업을 시작해서 9ms 시점에 작업 완료(요청에서 종료까지 : 7ms)
- B: 1ms부터 대기하다가, 9ms 시점에 작업을 시작해서 18ms 시점에 작업 완료(요청에서 종료까지 : 17ms)

이렇게 A → C → B의 순서로 처리하면 각 작업의 요청부터 종료까지 걸린 시간의 평균은 9ms(= (3 + 7 + 17) / 3)가 됩니다.

각 작업에 대해 [작업이 요청되는 시점, 작업의 소요시간]을 담은 2차원 배열 jobs가 매개변수로 주어질 때, 작업의 요청부터 종료까지 걸린 시간의 평균을 가장 줄이는 방법으로 처리하면 평균이 얼마가 되는지 return 하도록 solution 함수를 작성해주세요. (단, 소수점 이하의 수는 버립니다)

제한 사항

  • jobs의 길이는 1 이상 500 이하입니다.
  • jobs의 각 행은 하나의 작업에 대한 [작업이 요청되는 시점, 작업의 소요시간] 입니다.
  • 각 작업에 대해 작업이 요청되는 시간은 0 이상 1,000 이하입니다.
  • 각 작업에 대해 작업의 소요시간은 1 이상 1,000 이하입니다.
  • 하드디스크가 작업을 수행하고 있지 않을 때에는 먼저 요청이 들어온 작업부터 처리합니다. 

입출력

jobs return 
[[0, 3], [1, 9], [2, 6]] 9
[[7, 8],[3, 5 ], [9, 6]] 9

 

[ 문제 풀이 ]

- 이 문제 의 핵심은 최소 힙을 사용하여 성능을 고려하는 것이다!

- 작업 소요 시간이 적은 순서대로 일을 처리하면 된다 - > 작업 시간 기준 최소 힙을 구성

- 앞 선 작업이 시작~끝난 시간 동안 새로 들어온 작업들은 최소 힙에 넣어준다! 

- 해당 시간에 처리할 작업이 없으면 초를 증가 시킨다!

 

- 운영체제에서의 Shortest job first - non preemptive 와 유사

- 요청 시간 순서대로 대기열에 집어 놓되 우선 순위 큐를 사용하여 수행 시간이 짧은 작업을 앞으로 보냄 -> 힙을 사용 ( 힙은 우선순위 큐를 구현하기 좋은 자료구조 )

 

[ 문제 풀이 코드 ]

import heapq
def solution(jobs): # 작업소요 시간이 작은거 부터 빼는데 앞에 작업이 끝난 시간 기준 들어와있거나 딱 들어온 애들 중에서 고르면 됨!
    # heapq.heapify(jobs) # 이렇게 되면 최소힙이 되긴 함 ( 근데 들어오는 시간 기준 최소 힙이 되어버림 )
    answer =0 
    i,now = 0,0
    start = -1
    heap=[]
    while i < len(jobs): # 작업 개수 만큼은 일단 확인 되어야 함. 
        for j in jobs: # 작업 중에 처리 가능한 애들 판별 
            if start < j[0] <= now :
                heapq.heappush(heap, [j[1],j[0]]) # 소요 시간 기준 최소 힙
        if len(heap) > 0:
            job = heapq.heappop(heap)
            start = now # 현재 작업이 시작되는 시간?! # 이 시간 이후로 들어오는 애들 다시 힙에 넣어주기 위해서
            now += job[0] # 처리할 작업시간을 더해줌 ( 다음 작업의 시작시간이 될 것!)
            answer += now - job[1] # 대기 시간 추가
            i+=1 # 처리된 작업 추가
        else:
            now +=1 #처리할 작업이 없는 경우
    answer = answer // len(jobs) # 대기 시간 평균 구하기
    return answer

 


 

댓글