Programing/BaekJoon

[JAVA] 백준 1021 : 회전하는 큐

블스뜸 2025. 3. 31. 15:46

Queue에 이어서 Deque를 사용해야하는 문제이다
Deque는 큐의 반대 방향으로도 작동하는 알고리즘

index => 원하는 node의 value를 찾아 큐의 몇번째에 있는지 탐색
탐색한 위치 직전까지 (push(pop) <- 이 행동을 회전이라 칭한다) 회전을 하고 회전한 횟수만큼 카운트
그리고 index의 node를 pop을 해준다

import java.io.*;
import java.util.NoSuchElementException;
import java.util.StringTokenizer;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        NodeManager<Integer> nodeManager = new NodeManager<>();

        st = new StringTokenizer(br.readLine());
        int size = Integer.parseInt(st.nextToken());
        int searchCnt = Integer.parseInt(st.nextToken());

        for (int i = 1; i <= size; i++) {
            nodeManager.pushFront(new QueueNode<>(i));
        }

        st = new StringTokenizer(br.readLine());
        int[] searchValue = new int[searchCnt];
        for (int i = 0; i < searchCnt; i++) {
            searchValue[i] = Integer.parseInt(st.nextToken());
        }

        int rotateCnt = 0;
        for (int value : searchValue) {
            int index = nodeManager.indexOf(value);
            if (index <= nodeManager.getSize() / 2) {
                // 정방향 회전
                for (int i = 0; i < index; i++) {
                    nodeManager.pushFront(nodeManager.popFront());
                    rotateCnt++;
                }
            } else {
                // 역방향 회전
                for (int i = 0; i < nodeManager.getSize() - index; i++) {
                    nodeManager.pushBack(nodeManager.popBack());
                    rotateCnt++;
                }
            }
            nodeManager.popFront();
        }

        bw.write(String.valueOf(rotateCnt));

        bw.flush();
        bw.close();
        br.close();
    }
}

class QueueNode<T> {
    private final T value;
    private QueueNode<T> nextNode;
    private QueueNode<T> prevNode;

    public QueueNode(T value) {
        this.value = value;
        nextNode = null;
    }

    public T getValue() {
        return value;
    }

    public void setNextNode(QueueNode<T> nextNode) {
        this.nextNode = nextNode;
    }

    public QueueNode<T> getNextNode() {
        return nextNode;
    }

    public void setPrevNode(QueueNode<T> prevNode) {
        this.prevNode = prevNode;
    }

    public QueueNode<T> getPrevNode() {
        return prevNode;
    }
}

class NodeManager<T> {
    QueueNode<T> front, back;
    int size;

    public NodeManager() {
        front = back = null;
        size = 0;
    }

    public int getSize() {
        return size;
    }

    public boolean isEmpty() {
        return front == null;
    }

    public QueueNode<T> popFront() {
        if (isEmpty()) {
            throw new NoSuchElementException("Queue is empty");
        }
        QueueNode<T> node = front;
        if (front == back) {
            front = back = null;
        } else {
            front = front.getNextNode();
            front.setPrevNode(null);
        }
        size--;
        return node;
    }

    public void pushFront(QueueNode<T> node) {
        if (isEmpty()) {
            front = back = node;
        } else {
            back.setNextNode(node);
            node.setPrevNode(back);
            back = node;
        }
        size++;
    }

    public QueueNode<T> popBack() {
        if (isEmpty()) {
            throw new NoSuchElementException("Deque is empty");
        }
        QueueNode<T> node = back;
        if (front == back) {
            front = back = null;
        } else {
            back = back.getPrevNode();
            back.setNextNode(null);
        }
        size--;
        return node;
    }

    public void pushBack(QueueNode<T> node) {
        if (isEmpty()) {
            front = back = node;
        } else {
            front.setPrevNode(node);
            node.setNextNode(front);
            front = node;
        }
        size++;
    }

    public T peekFront() {
        if (isEmpty()) {
            throw new NoSuchElementException("Queue is empty");
        }
        return front.getValue();
    }

    public T peekBack() {
        if (isEmpty()) {
            throw new NoSuchElementException("Deque is empty");
        }
        return back.getValue();
    }

    public int indexOf(T value) {
        QueueNode<T> current = front;
        int index = 0;
        while (current != null) {
            if (current.getValue().equals(value)) {
                return index;
            }
            current = current.getNextNode();
            index++;
        }
        return -1; // 값을 찾지 못한 경우
    }
}