알고리즘 문제 풀이: 자바/LeetCode

649. Dota2 Senate

hueco 2025. 12. 2.

 

📌 Problem Link :

https://leetcode.com/problems/dota2-senate

 

Accepted :

class Solution {
    public String predictPartyVictory(String senate) {
        Queue<Character> queue = new ArrayDeque<>();
        int radiantCount = 0;
        int direCount = 0;

        // 초기 큐 구성 및 각 진영 카운트
        for (char ch : senate.toCharArray()) {
            queue.offer(ch);
            if (ch == 'R') radiantCount++;
            else direCount++;
        }

        int bannedRadiant = 0; // 다음에 등장하는 R을 제거할 권한 수
        int bannedDire = 0;    // 다음에 등장하는 D을 제거할 권한 수

        // 양쪽 진영이 남아있는 동안 반복
        while (radiantCount > 0 && direCount > 0) {
            char cur = queue.poll(); // null일 가능성 없음(문제 조건)
            if (cur == 'R') {
                if (bannedRadiant > 0) {
                    // 이 R은 금지되었으므로 제거 처리
                    bannedRadiant--;
                    radiantCount--;
                    continue;
                }
                // 이 R은 살아남아 라운드 끝에 다시 대기열에 들어가며,
                // 상대 진영(D) 중 하나를 금지할 권한을 얻음
                queue.offer(cur);
                bannedDire++;
            } else { // cur == 'D'
                if (bannedDire > 0) {
                    bannedDire--;
                    direCount--;
                    continue;
                }
                queue.offer(cur);
                bannedRadiant++;
            }
        }

        return radiantCount > 0 ? "Radiant" : "Dire";
    }
}

 

🧐 Review :

이 문제는 Radiant와 Dire 두 진영의 상원의원들이 서로를 제거해 나가며 최종 승자를 판별하는 시뮬레이션 문제입니다.

매 라운드마다 상원의원은 다른 상원의원의 권리를 박탈할 수 있고, 모든 상원의원이 같은 진영의 의원들로만 구성되어 있다면 승리를 선언할 수 있습니다.

 

핵심 아이디어: 큐(Queue)와 금지 권한

문제를 풀기에 앞서 상원의원들이 한 번 행동한 뒤 다시 라운드의 끝으로 돌아가며 반복되는 구조를 보고 자료구조 큐(Queue)가 떠올랐습니다. 큐를 사용하면 현재 차례인 의원이 행동 후 다시 대기열의 맨 뒤로 돌아가는 순환적인 라운드를 효과적으로 시뮬레이션할 수 있습니다.

추가적으로, 각 의원은 상대편의 다음 차례 의원을 금지할 권한을 가집니다. 이 금지 권한을 관리하기 위해 두 개의 변수를 사용합니다.

 

1. 초기 설정

큐 초기화: 입력 문자열 senate의 모든 상원의원을 순서대로 queue에 넣습니다. (R 또는 D)

카운트 초기화: radiantCountdireCount 변수에 각 진영의 초기 상원의원 수를 저장합니다.

금지 권한 초기화: bannedRadiant (다음에 등장하는 R을 제거할 권한 수)와 bannedDire (다음에 등장하는 D을 제거할 권한 수)를 0으로 초기화합니다.

2. 라운드 시뮬레이션

그리고 양쪽 진영이 남아있는 동안 반복문( while (radiantCount > 0 && direCount > 0) )을 돌면서 큐에서 현재 차례의 상원의원을 꺼냅니다.

Case 1: cur이 'R'일 때

금지 여부 확인: bannedRadiant > 0인지 확인합니다.

금지되었다면: 이 'R'은 권한을 박탈당했으므로 bannedRadiant를 1 감소시키고, radiantCount를 1 감소시킨 후 continue하여 이번 라운드에서 제거됩니다.

금지되지 않았다면: 자신은 권한 행사 후 라운드의 끝으로 돌아가므로 큐의 뒤에 다시 넣습니다. 상대 진영('D') 하나를 금지할 권한을 얻으므로 bannedDire 1 증가시킵니다.

Case 2: cur이 'D'일 때

금지 여부 확인: bannedDire > 0인지 확인합니다. (로직은 'R'의 경우와 대칭적입니다.)

금지되었다면: bannedDire를 1 감소시키고, direCount를 1 감소시킨 후 제거됩니다.

금지되지 않았다면: 큐의 뒤에 다시 넣습니다. 상대 진영('R') 금지할 권한을 얻으므로 bannedRadiant 1 증가시킵니다.

3. 최종 승자 판별

반복문은 한쪽 진영의 Count가 0이 될 때 종료됩니다. 즉, 더 이상 살아있는 (제거되지 않은) 상대 진영이 없다는 의미입니다.

최종적으로 radiantCount > 0이면 Radiant가 승리하며, 그렇지 않으면 Dire가 승리합니다.

'알고리즘 문제 풀이: 자바 > LeetCode' 카테고리의 다른 글

141. Linked List Cycle  (1) 2026.01.24
136. Single Number  (1) 2025.12.17
1137. N-th Tribonacci Number  (1) 2025.11.25
724. Find Pivot Index  (0) 2025.11.22
1. Two Sum  (0) 2025.11.22

댓글