문제
https://www.acmicpc.net/problem/1021
1021번: 회전하는 큐
첫째 줄에 큐의 크기 N과 뽑아내려고 하는 수의 개수 M이 주어진다. N은 50보다 작거나 같은 자연수이고, M은 N보다 작거나 같은 자연수이다. 둘째 줄에는 지민이가 뽑아내려고 하는 수의 위치가
www.acmicpc.net
내가 생각했던 풀이과정
1) 데크를 사용한다. 데크란 양방향 큐가 있는데 바로 데크(deque) 자료구조이다.
데크는 앞, 뒤 양쪽 방향에서 엘리먼트(element)를 추가하거나 제거할 수 있다.
2)
deque.rotate(iteration): iteration 횟수만큼 deque의 맨 뒷 값을 맨 앞으로 이동시킨다.
deque.rotate(-iteration): iteration 횟수만큼 deque의 맨 앞 값을 맨 뒤로 이동시킨다.
해당 숫자가 있는 index를 구해서 index값이 전체 length 길이의 절반보다 길면 deque의 뒤에서 앞으로 회전시키는 것이 더 효율적이고 그 반되면 deque의 앞에서 뒤로 값을 회전하는 것이 더 효율적이다.
나의 풀이
from collections import deque
N, M = map(int, input().split())
numbers = list(map(int, input().split()))
queue = deque(range(1, N+1))
count = 0
for idx in range(len(numbers)):
if numbers[idx] == queue[0]:
queue.popleft()
continue
queue_idx = queue.index(numbers[idx])
if queue_idx > len(queue) // 2:
queue.rotate(len(queue) - queue_idx)
count += (len(queue) - queue_idx)
elif queue_idx <= len(queue) // 2:
queue.rotate(-queue_idx)
count += queue_idx
queue.popleft()
print(count)
다른 사람의 풀이
새로 알게된 점, 확인해야할 점
데크(deque)의 개념
보통 큐(queue)는 선입선출(FIFO) 방식으로 작동한다. 반면, 양방향 큐가 있는데 그것이 바로 데크(deque)다.
즉, 앞, 뒤 양쪽 방향에서 엘리먼트(element)를 추가하거나 제거할 수 있다.
데크는 양 끝 엘리먼트의 append와 pop이 압도적으로 빠르다.
컨테이너(container)의 양끝 엘리먼트(element)에 접근하여 삽입 또는 제거를 할 경우, 일반적인 리스트(list)가 이러한 연산에 O(n)이 소요되는 데 반해, 데크(deque)는 O(1)로 접근 가능하다.
데크(deque) 사용법
데크는 다음처럼 임포트(import)해 사용한다.
from collections import deque
deq = deque()
# Add element to the start
deq.appendleft(10)
# Add element to the end
deq.append(0)
# Pop element from the start
deq.popleft()
# Pop element from the end
deq.pop()
데크(deque)에 존재하는 메서드(method)는 대략 다음과 같다.
- deque.append(item): item을 데크의 오른쪽 끝에 삽입한다.
- deque.appendleft(item): item을 데크의 왼쪽 끝에 삽입한다.
- deque.pop(): 데크의 오른쪽 끝 엘리먼트를 가져오는 동시에 데크에서 삭제한다.
- deque.popleft(): 데크의 왼쪽 끝 엘리먼트를 가져오는 동시에 데크에서 삭제한다.
- deque.extend(array): 주어진 배열(array)을 순환하면서 데크의 오른쪽에 추가한다.
- deque.extendleft(array): 주어진 배열(array)을 순환하면서 데크의 왼쪽에 추가한다.
- deque.remove(item): item을 데크에서 찾아 삭제한다.
- deque.rotate(num): 데크를 num만큼 회전한다(양수면 오른쪽, 음수면 왼쪽).
여기서 rotate() 메서드(method)가 특히 재밌는데, 설명이 부족하니 코드를 추가해 보겠다.
이렇게 양수 값 또는 음수 값을 파라미터(parameter)로 제공하여 데크(deque)를 좌, 우로 회전할 수 있다.
데크(deque), 언제, 왜 써야 하는가?
요약하자면, 데크(deque)는 스택처럼 사용할 수도 있고, 큐 처럼 사용할 수도 있다.
시작점의 값을 넣고 빼거나, 끝 점의 값을 넣고 빼는 데 최적화된 연산 속도를 제공한다.
즉, 대부분의 경우에 데크(deque)는 리스트(list)보다 월등한 옵션이다.
데크는 특히 push/pop 연산이 빈번한 알고리즘에서 리스트보다 월등한 속도를 자랑한다.
'알고리즘 > 백준 알고리즘' 카테고리의 다른 글
[Baekjoon] 백준 알고리즘: 2164 - 카드2 (0) | 2021.05.22 |
---|---|
[Baekjoon] 백준 알고리즘: 1049 - 기타줄 (0) | 2021.05.20 |
[Baekjoon] 백준 알고리즘: 1010 - 다리놓기 (0) | 2021.05.17 |
[Baekjoon] 백준 알고리즘: 1920번 - 수 찾기 (0) | 2021.05.06 |
[Baekjoon] 백준 알고리즘 - 1157: 단어 공부 (0) | 2021.04.21 |
댓글