문제 설명
[본 문제는 정확성과 효율성 테스트 각각 점수가 있는 문제입니다.]
"스노우타운"에서 호텔을 운영하고 있는 "스카피"는 호텔에 투숙하려는 고객들에게 방을 배정하려 합니다. 호텔에는 방이 총 k개 있으며, 각각의 방은 1번부터 k번까지 번호로 구분하고 있습니다. 처음에는 모든 방이 비어 있으며 "스카피"는 다음과 같은 규칙에 따라 고객에게 방을 배정하려고 합니다.
한 번에 한 명씩 신청한 순서대로 방을 배정합니다.
고객은 투숙하기 원하는 방 번호를 제출합니다.
고객이 원하는 방이 비어 있다면 즉시 배정합니다.
고객이 원하는 방이 이미 배정되어 있으면 원하는 방보다 번호가 크면서 비어있는 방 중 가장 번호가 작은 방을 배정합니다.
예를 들어, 방이 총 10개이고, 고객들이 원하는 방 번호가 순서대로 [1, 3, 4, 1, 3, 1] 일 경우 다음과 같이 방을 배정받게 됩니다.
원하는 방 번호 | 배정된 방 번호 |
---|---|
1 | 1 |
3 | 3 |
4 | 4 |
1 | 2 |
3 | 5 |
1 | 6 |
전체 방 개수 k와 고객들이 원하는 방 번호가 순서대로 들어있는 배열 room_number가 매개변수로 주어질 때, 각 고객에게 배정되는 방 번호를 순서대로 배열에 담아 return 하도록 solution 함수를 완성해주세요.
제한사항
k는 1 이상 10^12 이하인 자연수입니다.
room_number 배열의 크기는 1 이상 200,000 이하입니다.
room_number 배열 각 원소들의 값은 1 이상 k 이하인 자연수입니다.
room_number 배열은 모든 고객이 방을 배정받을 수 있는 경우만 입력으로 주어집니다.
예를 들어, k = 5, room_number = [5, 5] 와 같은 경우는 방을 배정받지 못하는 고객이 발생하므로 이런 경우는 입력으로 주어지지 않습니다.
입출력 예시
k | room_number | result |
---|---|---|
10 | [1,3,4,1,3,1] | [1,3,4,2,5,6] |
입출력 예 설명
첫 번째 ~ 세 번째 고객까지는 원하는 방이 비어 있으므로 즉시 배정받을 수 있습니다. 네 번째 고객의 경우 1번 방을 배정받기를 원했는데, 1번 방은 빈 방이 아니므로, 1번 보다 번호가 크고 비어 있는 방 중에서 가장 번호가 작은 방을 배정해야 합니다. 1번 보다 번호가 크면서 비어있는 방은 [2번, 5번, 6번...] 방이며, 이중 가장 번호가 작은 방은 2번 방입니다. 따라서 네 번째 고객은 2번 방을 배정받습니다. 마찬가지로 5, 6번째 고객은 각각 5번, 6번 방을 배정받게 됩니다.
풀이 코드
복습이라 재귀로 풀이한다는 것을 알고 있어서 다시 재귀로 풀이를 시도했다. (이게 왜 재귀 파트인지는 잘 모르겠지만,,,)
Level 4 인 이유가 있었던 것 같은데 생각이 안나서 처음 풀이는 실패했다. 아래 코드는 처음 풀이한 코드
def find_empty_room(want_room, check_in):
# 종료 조건 - 방을 배정할 수 있을 때 방 배정 후 재귀 반환
if want_room not in check_in:
check_in[want_room] = 0
return
# 방을 배정할 수 없다면, 순차 탐색으로 빈 방 찾아 재귀 호출
return find_empty_room(want_room + 1, check_in)
def solution(k, room_number):
check_in = dict()
for want_room in room_number:
find_empty_room(want_room, check_in)
return list(check_in)
배정된 방을 모아두는 check_in 에서 고객이 원하는 방을 뜻하는 want_room 을 찾을 때 O(1) 의 시간복잡도를 위해 check_in 을 리스트가 아닌 딕셔너리로 사용했음에도 시간초과가 발생했다. 도저히 이유를 알 수 없어서 책 해설을 참고했는데, 내 코드처럼 짠다면 최악의 경우 모든 고객이 100,000 번째 방을 원한다고 가정했을 때, 맨 마지막 고객은 100,000 만번 동안 재귀를 호출하게 된다는 것이다.
즉, 빈 방이 아니라면 그 다음 방을, 또 빈 방이 아니라면 그 다음 방을 ... 이런 순차 탐색 논리가 아니라 다른 아이디어가 필요하다고 한다.
먼저 개선된 코드는 아래와 같다.
solution() 함수는 기존과 동일하고 find_empty_room() 함수에서 조금 수정해줘야 한다. 글만 있으면 헷갈리니 room_number = [1,1] 인 경우 예시 그림도 첨부 ~
def find_empty_room(want_room, check_in):
# 종료 조건 - 방을 배정할 수 있을 때 배정하고 반환
if want_room not in check_in:
check_in[want_room] = want_room + 1
# want_room 방이 이미 배정되어 있다면 그 방 바로 다음 방이 아니라, want_room 방보다 번호가 크면서
# 비어있는 방 중 가장 작은 번호가 check_in[want_room] Value 값에 있으니 value 방을 원하는 방의
# 매개변수로 넘긴다. 이 때 또 이미 배정되어 있다면 위의 과정이 반복되다 배정되지 않은 방을 만나 종료 조건의
# if 분기문을 통해 방 배정 후 어느 방이 비어있었는지 empty_room 값으로 받아낸다.
empty_room = find_empty_room(check_in[want_room], check_in)
# 어느 방이 최종적으로 비어있었는지 확인되면 이전에 확인했던 방 번호 (이미 배정된 방 번호들) 의 value 값을
# 조정해야 한다.
check_in[want_room] = empty_room + 1
return empty_room
# solution() 는 달라진 것 없음
def solution(k, room_number):
answer = dict()
for want_room in room_number:
find_empty_room(want_room, answer)
return list(answer)
return answer
'알고리즘 정리' 카테고리의 다른 글
파이썬(Python) 알고리즘 문제풀이 카펫 [프로그래머스 / 완전탐색] (0) | 2023.05.31 |
---|---|
파이썬(Python) 알고리즘 문제풀이 모의고사 [프로그래머스 / 완전탐색] (0) | 2023.05.31 |
파이썬(Python) 알고리즘 문제풀이 모음사전 [프로그래머스 / 문자열] (0) | 2023.05.30 |
파이썬(Python) 알고리즘 문제풀이 하노이의 탑 [프로그래머스 / 문자열] (0) | 2023.05.29 |
파이썬(Python) 알고리즘 문제풀이 신규 아이디 추천 [프로그래머스 / 문자열] (0) | 2023.05.28 |