목차
1. 문제
2. 입출력 예시
입력 예시 | 출력 예시 |
---|---|
3 10 20 40 | 100 |
3. 문제 풀이
이 문제는 시간관리에 있어서 애먹었던 문제이다. 문제를 해결하기 위한 논리는 매우 단순하다.
- 비교할 카드 묶음의 수량(
n
)을 입력받는다. - 만약에 카드 묶음의 수량이 1개일 경우는 비교할 필요가 없으니 결과값을 0으로 출력하고, 그 외에는 결과값(
total
)을 0으로 초기화한 후 카드 묶음의 수량만큼 반복하여 카드 묶음의 크기를 입력받아 리스트(lst
)에 추가한다. - 비교를 할 때 카드 묶음의 크기가 작은 순으로 연산을 수행해야 최솟값이 나오므로, 리스트를 오름차순으로 정렬한다.
while
문을 통해 리스트의 크기가 1보다 클 때까지 반복하는 동안 리스트의 첫 번째 요소와 그 다음 요소를 리스트에서 추출(pop
)하여 이 둘을 더한다. 이렇게 더한 값을 리스트의 첫 번째 요소로 삽입하고, 이 값을 결과값에 더한다. (아래 표 참조)- 반복이 종료되면 결과값을 출력한다.
반복 횟수 | 리스트(전) | 리스트(후) | 결과값 |
---|---|---|---|
0 | [] |
[10, 20, 40] |
0 |
1 | [10, 20, 40] |
[30, 40] |
30 (10 + 20) |
2 | [30, 40] |
[70] |
100 (30 + (30 + 40)) |
이를 리스트를 사용해서 구현하면 아래와 같다. 그러나 이 코드를 제출할 경우에는 시간초과
라는 결과를 받게 된다.
import sys
n = int(input())
if n == 1:
print(0)
else:
total = 0
lst = [int(sys.stdin.readline()) for _ in range(n)]
lst.sort()
while len(lst) > 1:
tmp1 = lst.pop(0)
tmp2 = lst.pop(0)
lst.insert(0, tmp1 + tmp2)
total += tmp1 + tmp2
print(total)
이를 해결하기 위한 방법으로 큐(queue
)를 생각해보았으나, 이는 FIFO(First-In First-Out
) 즉, 먼저 들어온 데이터를 먼저 내보내는 형식이기 때문에 맨 앞에 요소를 추가할 수 없다. 따라서, 우선순위가 높은 데이터를 먼저 내보내는 우선순위 큐(Priority Queue
)를 사용하여야 한다. 위 코드에서 구현한 방식이 바로 우선순위 큐의 작동 원리인 셈이다. 그렇다면 왜 리스트로 이를 구현했을 때에는 시간복잡도에 차이가 발생할까?
리스트에서 요소를 추가하고 이를 우선순위를 기준으로 정렬하였다고 해보자. 맨 앞에 위치한 요소는 우선순위가 가장 높은 요소이다. 이를 리스트에서 호출할 때 맨 앞에 위치한 인덱스(Index
)를 사용하면 되므로 시간복잡도가 크지 않다. 그러나 리스트에 위치한 요소를 삭제할 때에는 해당 요소 뒤에 위치한 요소들의 인덱스를 전부 앞당겨주어야 한다. 이와 마찬가지로 리스트의 맨 앞에 요소를 추가할 때, 기존에 위치하던 요소의 인덱스를 전부 뒤로 밀어내야 한다. 만약 추가할 자료가 n
개라고 가정했을 때 시간복잡도는 O(n)이 된다. 그러나 우선순위 큐는 힙(heap
) 기반으로 되어 있으며, 데이터 삽입 및 삭제 시 시간복잡도는 O(log₂N)이다. 이에 대해서는 따로 자세히 포스팅하도록 할 예정이다.
우선순위 큐를 사용한 코드는 아래와 같으며, 메모리 31,672 KB
, 시간 220 ms
가 소요되었다.
import sys
import heapq
n = int(input())
if n == 1:
print(0)
else:
total = 0
lst = [int(sys.stdin.readline()) for _ in range(n)]
lst.sort()
heapq.heapify(lst)
while len(lst) > 1:
tmp1 = heapq.heappop(lst)
tmp2 = heapq.heappop(lst)
heapq.heappush(lst, tmp1 + tmp2)
total += tmp1 + tmp2
print(total)
'Algorithm > Baekjoon' 카테고리의 다른 글
Baekjoon #1744 - 수 묶기 (0) | 2021.03.26 |
---|---|
Baekjoon #13305 - 주유소 (0) | 2021.03.25 |
Baekjoon #4796 - 캠핑 (0) | 2021.03.25 |
Baekjoon #1339 - 단어 수학 (0) | 2021.03.24 |
Baekjoon #10162 - 전자레인지 (0) | 2021.03.24 |