문제 링크
https://www.acmicpc.net/problem/1021
풀이
- 양방향 순환 큐이기 때문에 덱(
Deque
,ArrayDeque
)을 사용하려 했으나, 연결 리스트(LinkedList
)로도 구현이 가능하다는 스터디 팀원의 설명을 듣고 연결 리스트로 구현해보았다.ArrayDeque
와LinkedList
모두Deque
인터페이스를 구현한다.- 나중에 알게 된 사실이지만, 큐와 덱을 구현할 때는
LinkedList
보다ArrayDeque
를 사용하는 것이 더 효율적이라고 한다. (자바 API Documentation 피셜)
- 첫 번째 원소를 뽑아내는 1번 연산은 결과값
result
에 포함하지 않는다. 오직 2번, 3번 연산만 포함한다. - 뽑고자 하는 원소가 어느 위치에 있는지 확인 후, 첫 번째 원소로부터 더 가까운 방향으로 원소들을 이동시킨다.
LinkedList
에도indexOf()
메소드가 있기 때문에 위치(인덱스)를 쉽게 얻을 수 있다.- 첫 번째 원소로부터 오른쪽 거리를
indexOf()
로 구하고, 전체 원소 개수에서 오른쪽 거리를 빼면 왼쪽 거리를 구할 수 있다. - 거리가 더 가까운 방향을 정한 후 뽑고자 하는 원소가 첫 번째 원소로 올 때까지
offer
와poll
을 반복한다. 여기서는 양방향 큐이므로offerFirst()
,offerLast()
,pollFirst()
,pollLast()
를 사용한다.
- 첫 번째 원소로부터 오른쪽 거리를
- 뽑고 싶은 원소에 다다르면 해당 원소를 뽑고,
result
에 왼쪽 혹은 오른쪽으로 이동한 거리를 더한다. 이제 뽑아낼 수의 개수m
만큼 반복하면 원하는 값을 구할 수 있다.
소스 코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
st = new StringTokenizer(br.readLine());
int n = Integer.parseInt(st.nextToken());
int m = Integer.parseInt(st.nextToken());
// 큐 초기화 (연결 리스트 사용)
LinkedList<Integer> queue = new LinkedList<>();
for (int i = 1; i <= n; i++) queue.offerLast(i);
st = new StringTokenizer(br.readLine());
int result = 0;
for (int i = 0; i < m; i++) {
int target = Integer.parseInt(st.nextToken());
if (queue.peekFirst() == target) {
// 첫 번째 원소가 뽑아낼 수일 경우
queue.pollFirst();
} else {
// 왼쪽과 오른쪽 중 더 짧은 거리를 이동
int rightDist = queue.indexOf(target);
int leftDist = queue.size() - rightDist;
if (leftDist < rightDist) {
while (queue.peekFirst() != target) {
queue.offerFirst(queue.pollLast());
}
// 첫 번째 원소 추출
queue.pollFirst();
result += leftDist;
} else {
while (queue.peekFirst() != target) {
queue.offerLast(queue.pollFirst());
}
// 첫 번째 원소 추출
queue.pollFirst();
result += rightDist;
}
}
}
System.out.println(result);
br.close();
}
}