[알고리즘] 회전하는큐

package org.example.회전하는큐;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.text.MessageFormat;
import java.util.*;

/**
 * packageName    : org.example.회전하는큐
 * fileName       : Main
 * author         : ipeac
 * date           : 2023-09-10
 * description    :
 * ===========================================================
 * DATE              AUTHOR             NOTE
 * -----------------------------------------------------------
 * 2023-09-10        ipeac       최초 생성
 */
public class Main {
    public static void main(String[] args) {
        try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in));) {
            String input = br.readLine();
            String[] split = input.split(" ");
            int n = Integer.parseInt(split[0]);
            if (!(1 <= n && n <= 50)) {
                String errorMessage = MessageFormat.format("n 의 범위는 1 <= n <= 50 입니다. n = {0}", n);
                throw new IllegalArgumentException(errorMessage);
            }
            int m = Integer.parseInt(split[1]);
            if (!(1 <= m && m <= n)) {
                String errorMessage = MessageFormat.format("m 의 범위는 1 <= m <= {0} 입니다. m = {1}", n, m);
                throw new IllegalArgumentException(errorMessage);
            }
            
            StringTokenizer st = new StringTokenizer(br.readLine(), " ");
            
            QueueRotator<Integer> queueRotator = new QueueRotator<>();
            for (int i = 1; i <= n; i++) {
                queueRotator.add(i);
            }
            
            List<Integer> targets = new ArrayList<>();
            
            while (st.hasMoreTokens()) {
                int target = Integer.parseInt(st.nextToken());
                if (!(1 <= target && target <= n)) {
                    String errorMessage = MessageFormat.format("target 의 범위는 1 <= target <= {0} 입니다. target = {1}", n, target);
                    throw new IllegalArgumentException(errorMessage);
                }
                targets.add(target);
            }
            
            int answer = 0;
            
            for (Integer target : targets) {
                // 중앙인덱스와 비교값간의 차이
                answer += queueRotator.pollElementBy(target);
            }
            System.out.println(answer);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    public static class QueueRotator<T> {
        
        private final LinkedList<T> queue;
        
        public QueueRotator() {
            this.queue = new LinkedList<>();
        }
        
        private LinkedList<T> add(T element) {
            queue.add(element);
            return queue;
        }
        
        public int pollElementBy(T element) {
            Objects.requireNonNull(element, "element 는 null 이 될 수 없습니다.");
            // 타겟 값과 중앙값의 인덱스 차이비교하여 큐를 회전시킨다.
            boolean isMidIndexGreater = isMidIndexGreaterThanIndexOf(element);
            if (isMidIndexGreater) {
                return pollFirstUntilSame(element);
            }
            return pollLastUntilSame(element);
        }
        
        private int pollLastUntilSame(T element) {
							//NPE 방지 해야함 ㅇㅇ
            int affected = 0;
            while (true) {
                T last = queue.getLast();
                
                if (Objects.equals(last, element)) {
                    pollLast();
                    // 마지막 값을 제일 앞으로 보내는 동시에 값이 사라지기에, affected 를 1 증가시킨다.
                    affected++;
                    break;
                }
                pollLast();
                // 맨 앞으로 보낸다.
                addFirst(last);
                affected++;
            }
            return affected;
        }
        
        private int pollFirstUntilSame(T element) {
						//여기도 NPE 방지해야하긴함.
            int affected = 0;
            while (true) {
                T first = queue.getFirst();
                if (Objects.equals(first, element)) {
                    pollFirst();
                    break;
                }
                pollFirst();
                // 맨 뒤로 보낸다.
                addLast(first);
                affected++;
            }
            return affected;
        }
        
        private boolean isMidIndexGreaterThanIndexOf(T element) {
            Objects.requireNonNull(element, "element 는 null 이 될 수 없습니다.");
            int elementIndex = queue.indexOf(element);
            int midIndex = queue.size() / 2;
            return elementIndex <= midIndex;
        }
        
        private LinkedList<T> pollFirst() {
            queue.pollFirst();
            return queue;
        }
        
        private Queue<T> pollLast() {
            queue.pollLast();
            return queue;
        }
        
        private Queue<T> addFirst(T element) {
            queue.addFirst(element);
            return queue;
        }
        
        private Queue<T> addLast(T element) {
            queue.addLast(element);
            return queue;
        }
        
    }
    
}
  • 너무 어렵게 푼거같다..
  • 그냥 중앙인덱스 기준으로 오른쪽이면 오른쪽 큐값 제거제거
    • 오른쪽 값의 경우 별도로
  • 왼쪽이면 왼쪽값 제거제거
  • 카운트 리턴 이 끝이다.

클래스: QueueRotator

  • pollElementBy: 타겟 요소를 찾아 큐에서 빼내는 데 필요한 회전 횟수를 반환합니다.
  • isMidIndexGreaterThanIndexOf: 타겟 요소의 인덱스가 큐의 중간 인덱스보다 작거나 같은지 판단합니다.
  • pollFirstUntilSamepollLastUntilSame: 타겟 요소를 찾을 때까지 큐를 앞 또는 뒤로 회전시킵니다.

Uploaded by N2T

'자바 > 알고리즘' 카테고리의 다른 글

[알고리즘] 생태학  (0) 2023.09.24
[알고리즘] __**주사위 놀이하는 함수**__  (0) 2023.09.23
[알고리즘] four squares  (0) 2023.09.10
[알고리즘]병사 배치하기  (0) 2023.09.01
[알고리즘]한줄로 서기  (0) 2023.08.31