알고리즘

자바 - 백준 17609 / 회문

kdozlo 2024. 9. 13. 13:35

백준 17609 / 회문
골드5

구현 방법

양끝 문자가 같은 단어를 구하는 문제입니다.
투포인터를 이용하여 단어 비교하는 것이 핵심입니다.


문제에서는 한 문자를 제외 했을 때도 가능하다는 조건이 있어서 투 포인터로 돌리고 만약 두 문자가 다르다면 오른쪽 끝이나 왼쪽 끝을 기준으로 현재문자의 다음 문자로 이동하여 비교하는 식으로 구현했습니다.
하지만 이 경우 예외가 존재했습니다.
예를들어 abcbbca인 경우, 두번째 차례에서 b와 c가 다릅니다. 이경우 두가지 방법이 있습니다.
첫번째 방법. 왼쪽 끝인 b 다음 문자 c와 오른쪽 끝 c를 같다고 생각하는 경우
두번째 방법. 오른쪽 끝인 c 다음 문자인 b와 왼쪽 끝 b를 같다고 생각하는 경우
첫번째 방법의 경우는 문제의 조건을 만족합니다.
하지만 두번째 방법의 경우 결국 문제의 조건을 만족하지 못합니다.


따라서 오른쪽 끝을 제외하고 다음 단계로 가는 경우와 왼쪽 끝을 제외하고 다음 단계로 가는 경우 모두를 계산하여 답을 구해야 합니다. 여기서 속도를 높이기 위해 처음 경우에서 다른 문자가 발견된 위치를 저장하여, 두번째 경우에서 계산할 때는 다른 문자 발견 위치부터 시작하는 방법을 사용했습니다.

코드

import java.util.*;
import java.io.*;

/**
 * 백준 17609
 * 회문
 * 골드5
 * https://www.acmicpc.net/problem/17609
 */
public class Boj17609 {

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder sb = new StringBuilder();

        int T = Integer.parseInt(br.readLine());
        String cur;
        for(int i = 0; i < T; i++) {
            cur = br.readLine();

            int answer1 = 0;
            int left = 0;
            int right = cur.length() - 1;
            int left2 = 0;
            int right2 = cur.length() - 1;

            while(left < right) {
                if(cur.charAt(left) == cur.charAt(right)) {
                    left++;
                    right--;
                    continue;
                }

                if(++answer1 == 2) break;

                left2 = left++;
                right2 = right;

            }

            if(answer1 == 2) {
                answer1 = 0;

                while(left2 < right2) {
                    if(cur.charAt(left2) == cur.charAt(right2)) {
                        left2++;
                        right2--;
                        continue;
                    }

                    if(++answer1 == 2) break;

                    right2--;
                }
            }

            sb.append(answer1).append("\n");
        }

        System.out.print(sb);
    }
}

느낀 점

이 문제는 단일 책임 원칙을 적용해서 코드를 구현하면 훨씬 깔끔하게 짤 수 있다고 느꼈습니다.

또 예외 케이스 찾는 연습 방법에 대해서도 생각해봤습니다.
1. 먼저 의심되는 곳을 찾습니다.(입렵값 범위, 계산 데이터 범위, 등등)
2. 의심되는 것을 바탕으로 예외 케이스를 직접 생각해봅니다.

예외 케이스 찾는 연습을 많이 하면 센스가 생겨서 많은 도움이 될것이라고 생각했습니다.