2019 카카오 개발자 겨울 인턴십 - 64063. 호텔 방 배정
Python 풀이
풀이
Union-Find 알고리즘을 이용하여 풀면 될 것이라고 직감이 왔다.
[백준] 10775. 공항 문제와 굉장히 유사했기 때문.
그런데 이제, 효율성을 위해 알고리즘을 조금 바꿀 필요가 있었다.
Find는 그대로 두지만, Union하는 과정에서,
무조건 숫자가 높은 쪽이 root가 되도록 하는 것.
그렇게 하고, n번의 방이 찰 때마다,
n과 n+1을 Union하는 방식으로 진행한다.
이 예시에서는,
k = 10 room_number = [1,3,4,1,3,1]
맨 처음엔 dictionary가 이 상태일 것이다.
{1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, 10: 10}
1~3번째 손님에게 방을 주어 1, 3, 4번 방을 채우면, 아래와 같은 상황이 된다.
{1: 2, 2: 2, 3: 4, 4: 5, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, 10: 10}
이후, 4번째 손님의 방을 줄 때는, find(1)을 수행하면 결과값이 2이므로, 2번 방에 투숙시킨다.
{1: 2, 2: 3, 3: 4, 4: 5, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, 10: 10}
5번째 손님은 find(3)을 수행하면, 결과값이 5이므로, 5번 방에 투숙시킨다.
{1: 2, 2: 3, 3: 4, 4: 5, 5: 6, 6: 6, 7: 7, 8: 8, 9: 9, 10: 10}
마지막으로 6번째 손님은, find(1) == 6이므로, 6번 방에 투숙시키면 된다.
{1: 2, 2: 3, 3: 4, 4: 5, 5: 6, 6: 6, 7: 7, 8: 8, 9: 9, 10: 10}
(Find, Union과정에서의 간소화는 무시하였음)
전체 Code
import sys sys.setrecursionlimit(10000) def solution(k, room_number): room = {i: i for i in range(1, k+1)} # Union-Find 구현 def find(x): if room[x] == x: return x k = find(room[x]) # Union-Find -> Root까지의 경로 압축 (line 13) room[x] = k return k # union(n, n+1)로만 사용 def union(x, y): rootX = find(x) rootY = find(y) room[rootX] = rootY # 시작 answer = [] for p in room_number: root = find(p) answer.append(root) if root == k: continue union(root, root+1) return answer
아래 코드는 find연산에서 재귀 횟수 초과 방지를 위함.
import sys sys.setrecursionlimit(10000)
이렇게 풀었더니, 효율성 5, 6, 7번에서 시간 초과가 났다.
조금 더 시간을 단축할 방법을 모색.
풀이 2
여러 시도를 해봤고,
room = {i: i for i in range(1, k+1)}
으로 맨 처음에 초기화를 시켜준 것이 효율성에 문제가 있었다.
이를 없애고, 빈 dictionary에서 시작하여
빈 방(존재하지 않는 Node)를 만났을 때 Node를 만들어 주면서 진행하는 것으로 코드 변경.
그렇게 했더니 성공했다.
전체 Code
import sys sys.setrecursionlimit(10000) def solution(k, room_number): room = {} # Find 구현 def find(x): if x not in room.keys(): room[x] = x+1 return x if room[x] == x: return x k = find(room[x]) # Union-Find -> Root까지의 경로 압축 (line 13) room[x] = k return k # 시작 answer = [] for p in room_number: if p not in room.keys(): room[p] = p+1 answer.append(p) else: root = find(p) answer.append(root) return answer