: Double-Ended Queue = 앞뒤로 모두 pop할 수 있는 queue
: 일단 맨 앞에서 원소를 뽑아내야 하므로 선입후출 방식을 큐를 써야 합니다.
: 추가적으로 왼쪽 이동, 오른쪽 이동 연산도 원소를 pop 앞 or 뒤에 push한 것입니다.
: 세 가지 연산을 모두 O(1)로 할 수 있는 deque 자료구조를 사용합시다.
: 먼저 M만큼 반복문 1개
: 그 반복문 안에서 큐의 연산을 실제로 수행하는 반복문 1개로 (내부의 dq 연산은 O(1))
: O(N**2)이 예상됩니다. n은 최대 50이므로 시간 내에 해결이 가능합니다.
// 데큐 구현
struct Deque {
//✅ deque를 구현할 때는 무조건 더블 스택큐를 사용합니다.
var input = [Int]()
var output = [Int]()
var count: Int {
return input.count + output.count
}
//✅ queue에서 특정 값의 index를 구하는 함수
func index(of n: Int) -> Int {
let queue = output.reversed() + input // 원래 queue 모양대로 만들어서
return queue.firstIndex(of: n)! // index를 구해서 리턴
}
//✅ 오른쪽에 push = 원래 queue와 동일하게 구현
mutating func pushRight(_ n: Int) {
input.append(n)
}
//✅ 왼쪽에 push
// = queue에서 바로 pop될 자리
// = output의 맨 뒤에 넣으면 됨
mutating func pushLeft(_ n: Int) {
output.append(n)
}
//✅ 왼쪽에서 pop = 원래 queue와 동일하게 구현
mutating func popLeft() -> Int {
if output.isEmpty {
output = input.reversed()
input.removeAll()
}
return output.popLast()!
}
//✅ 오른쪽에서 pop
// = queue에서 방금 push된 자리
// input의 맨 마지막꺼 빼면 됨
mutating func popRight() -> Int {
if input.isEmpty {
input = output.reversed()
output.removeAll()
}
return input.popLast()!
}
}
//✅ 문제 풀이를 위한 메소드 구현
extension Deque {
mutating func moveLeft() {
self.pushRight(self.popLeft())
}
mutating func moveRight() {
self.pushLeft(self.popRight())
}
}
// 입력 받기
let input = readLine()!.split(separator: " ").map { Int(String($0))! }
let N = input[0], M = input[1]
let toPops = readLine()!.split(separator: " ").map { Int(String($0))! }
// deque 만들기
var deque = Deque()
for i in 1...N {
deque.pushRight(i)
}
// 2, 3번 연산 횟수를 저장할 변수
var cnt = 0
// pop 해야할 수 반복문
toPops.forEach { toPop in
let moveLeftCount = deque.index(of: toPop) //👉 왼쪽으로 옮겨서 뺄 때 횟수
let moveRightCount = deque.count - moveLeftCount //👉 오른쪽으로 옮겨서 뺄 때 횟수
// 더 적은 쪽으로 선택해서 빼기
if moveLeftCount < moveRightCount {
for _ in 0..<moveLeftCount {
deque.moveLeft()
}
_ = deque.popLeft()
cnt += moveLeftCount
} else {
for _ in 0..<moveRightCount {
deque.moveRight()
}
_ = deque.popLeft()
cnt += moveRightCount
}
}
print(cnt)