백준 문제 풀이

투 포인터 > 17609번

qazwsxedc9 2022. 8. 15. 17:10

17609번

 

2개의 포인터가 각각 배열의 시작점과 끝점에 위치하여 반대로 이동하는 방법을 사용

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class baekjoon17609 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine());
        StringBuilder sb = new StringBuilder();
        for(int i = 0; i<n; i++) {
            String str = br.readLine();
            sb.append(twoPointer(str)+"\n");
        }
        System.out.println(sb);
    }
    public static int twoPointer (String str) {
        char [] arr = str.toCharArray();
        int count = 0;
        int start = 0;
        int end = arr.length-1;
        while(start<=end) {
            if(arr[start] == arr[end]) { // 양쪽 문자가 일치할 경우
                start++;
                end--;
            } else { // 다른 경우
                count = 1;
                int left = start+1; // 왼쪽 문자 무시 후 회문 여부 체크
                int right = end;

                while(left<=right) {
                    if(arr[left] == arr[right]) {
                        left++;
                        right--;
                    } else {
                        count++;
                        break;
                    }
                }
                left = start;
                right = end-1; // 오른쪽 문자 무시 후 회문 여부 체크
                while(left<=right) {
                    if(arr[left] == arr[right]) {
                        left++;
                        right--;
                    } else {
                        count++;
                        break;
                    }
                }
                if(count>=2) { // 왼쪽과 오른쪽 모두 다른 경우 > 3, 둘 중 하나만 다른 경우 > 2
                    return count-1;
                } else {
                    return count;
                }
            }
        }
        return count; // 회문이라면 0 반환
    }
}

 

코드가 지저분한 느낌이 들어 다른 방법도 찾아보았다

 

// 회문 여부를 체크하는 메서드와 유사 회문 여부를 체크하는 메서드 두 가지를 별도로 만든다

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class baekjoon17609_ {
    static char [] arr;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine());
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < n; i++) {
            arr = br.readLine().toCharArray();
            int start = 0;
            int end = arr.length-1;
            if(checkP(start, end)) { // 회문인 경우
                sb.append(0+"\n");
                continue;
            }
            if(checkS(start, end)) {
                sb.append(1+"\n");
            } else {
                sb.append(2+"\n");
            }
        }
        System.out.println(sb);
    }

    public static boolean checkP(int start, int end) { // 회문 여부 체크
        while (start <= end) {
            if (arr[start] != (arr[end])) { // 두 포인터가 가리키는 문자가 달라지는 순간 false 반환
                return false;
            }
            start++;
            end--;
        }
        return true;
    }

    public static boolean checkS(int start, int end) { // 유사 회문 여부 체크
        while (start <= end) {
            if (arr[start]!=(arr[end])) { // 두 포인터가 가리키는 문자가 다른 경우
                boolean b1 = checkP(start + 1, end); // 왼쪽 문자 무시하고 나머지가 회문인지 체크
                boolean b2 = checkP(start, end - 1); // 오른쪽 문자 무시하고 나머지가 회문인지 체크
                if (b1 == false && b2 == false) {
                    return false; // 둘 다 회문이 될 수 없으면 유사 회문도 될 수 없음
                } else {
                    return true;
                }
            }
            start++;
            end--;
        }
        return true; // 회문인 경우 true 반환
    }
}

 

두 가지 풀이 모두 원리는 동일

 

양 끝에서 탐색을 시작

 

두 포인터가 가리키는 문자가 같은 경우 왼쪽 포인터는 오른쪽으로 한 칸 이동, 오른쪽 포인터는 왼쪽으로 한 칸 이동

 

두 포인터가 가리키는 문자가 달라지는 순간, 더 이상 회문은 될 수 없다

  • 왼쪽 문자를 무시하고 다음 문자부터 끝 문자까지 회문인지 체크
  • 오른쪽 문자를 무시하고 처음 문자부터 끝 문자 앞까지 회문인지 체크

 

둘 중 하나라도 만족할 경우 유사 회문이 될 수 있다

'백준 문제 풀이' 카테고리의 다른 글

분할 정복 > 1629번, 10830번  (0) 2022.08.19
투 포인터 > 22862번  (0) 2022.08.17
DFS와 BFS > 1926번, 2468번  (0) 2022.08.14
다익스트라 > 4485번 / 그리디 > 1339번  (0) 2022.08.12
이진 탐색 > 1939번, 3079번  (0) 2022.08.10