백준 팰린드로미터

KIMYEONGJUN·2025년 12월 29일
post-thumbnail

문제

내가 생각했을때 문제에서 원하는부분

입력은 여러 테스트 케이스로 이루어져 있다.
각 테스트 케이스는 한 줄로 이루어져 있고, 현재 승환이의 주행 거리계에 적혀있는 수가 주어진다.
이 숫자는 2자리와 9자리 사이(포함)이다.
예를 들어, 주행 거리계에 적히는 숫자의 갯수는, 입력으로 주어진 수의 숫자의 갯수와 같다.
그래서, 입력이 00456이라면, 5자리 숫자이다. 마지막 줄에는 0이 적혀있다.

각 테스트 케이스에 대해서 주행 거리계의 수가 팰린드롬이 되기 위해 주행해야 하는 최소 거리를 출력한다.
만약 이미 팰린드롬이라면 0을 출력한다.

내가 이 문제를 보고 생각해본 부분

main 메서드:
입출력 준비: 이전과 동일하게 BufferedReader로 입력을 효율적으로 읽고, StringBuilder로 최종 결과를 모아 한 번에 출력하여 입출력 성능을 높인다.
char[] charBuffer = new char[9];
최대 9자리 숫자가 주어지므로, 9칸짜리 char 배열 charBuffer를 main 메서드 시작 시 딱 한 번만 생성한다.
이 charBuffer는 이후 모든 isPalindrome 호출에서 재활용된다. 
String 객체를 새로 만들지 않고, 이 charBuffer의 내용을 계속 덮어쓰면서 팰린드롬 검사를 진행한다.
테스트 케이스 처리 루프:
while(true) 루프를 돌면서 한 줄씩 line을 읽어온다.
"0"이 입력되면 종료한다.
originalLength는 현재 입력된 숫자의 자리수를 기억한다. (00121이면 5)
currentNumber는 입력받은 line을 long 타입으로 변환한 값이다. 
long을 사용하는 이유는 숫자가 커질 수 있기 때문이다.
distance는 현재 팰린드롬이 되기까지 얼마나 주행했는지 기록하는 변수이다.
팰린드롬 찾기 내부 루프:
while(true) 루프를 돌며 팰린드롬을 찾을 때까지 currentNumber를 1씩 증가시킨다.
if(isPalindrome(currentNumber, originalLength, charBuffer)): 여기가 가장 중요한 변경점이다.
currentNumber: 현재 확인하려는 숫자.
originalLength: 처음 입력받은 숫자의 자리수.
charBuffer: 위에서 딱 한 번만 생성한 그 배열을 넘겨준다.
isPalindrome 메서드는 이제 currentNumber를 이 charBuffer에 "문자열처럼" 채워 넣고 팰린드롬을 검사한다.
이 과정에서 새로운 String 객체는 전혀 생성되지 않는다.
만약 isPalindrome이 true를 반환하면, distance를 StringBuilder에 추가하고 현재 테스트 케이스를 위한 루프를 break한다.
currentNumber++, distance++: 팰린드롬이 아니면 숫자를 1 늘리고 주행 거리도 1 늘린다.
isPalindrome(long num, int originalLength, char[] charBuffer) 메서드:
새로운 시그니처: 이 메서드는 더 이상 String 객체를 입력받지 않는다. 
대신, 확인하려는 long 타입 숫자 (num), 필요한 자리수 (originalLength), 그리고 재사용할 char 배열 (charBuffer)를 인자로 받는다.
charBuffer 채워넣기 (새로운 String 생성 방지!):
int i = originalLength - 1;: charBuffer의 가장 마지막 인덱스부터 채워나가기 시작한다.
num == 0 특별 처리: 만약 num이 0인 경우 (예: 입력이 "000"이면 currentNumber도 처음엔 0), charBuffer를 모두 '0'으로 채운다.
숫자를 charBuffer에 채우기:
while(num > 0) 루프를 돌면서 num % 10을 통해 숫자의 가장 낮은 자리부터 한 자리씩 추출한다.
추출한 숫자에 '0'을 더해 char 타입으로 변환하고, charBuffer[i--]에 저장한다. (예: 숫자 5를 '5' 문자로) i--를 통해 뒤에서 앞으로 채워나간다.
num /= 10으로 num을 10분의 1로 줄여 다음 자리를 준비한다.
선행 0 채우기: while (i >= 0) 루프는 아직 charBuffer에 채워지지 않은 앞부분을 모두 '0'으로 채운다.
이렇게 함으로써 00121처럼 원래 자리수를 유지하면서 앞에 0이 붙는 경우를 완벽하게 재현할 수 있다.
예를 들어, originalLength가 5인데 currentNumber가 121이었다면, charBuffer는 먼저 __121 (밑줄은 비어있는 칸)이 채워지고, 이 루프를 통해 00121이 된다.
팰린드롬 검사: charBuffer가 완벽하게 채워진 후, 이 charBuffer의 양 끝에서부터 문자를 비교하며 팰린드롬 여부를 판단한다. 
기존 isPalindrome(String s)와 유사하지만, String 객체 대신 char 배열을 직접 사용한다.

코드로 구현

package baekjoon.baekjoon_31;

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

// 백준 4096번 문제
public class Main1251 {
    // 숫자를 char 배열로 변환하고 팰린드롬인지 확인하는 메서드
    public static boolean isPalindrome(long num, int originalLength, char[] charBuffer) {
        // num을 문자열로 변환하면서 charBuffer에 저장하고, 앞에 0을 채웁니다.
        int i = originalLength - 1; // 버퍼의 마지막 인덱스부터 채워넣기 시작
        if (num == 0) { // 0인 경우를 처리 (예: "000")
            for (int k = 0; k < originalLength; k++) {
                charBuffer[k] = '0';
            }
        } else {
            // 숫자를 뒤에서부터 문자열 버퍼에 채우기
            while (num > 0) {
                charBuffer[i--] = (char) ((num % 10) + '0'); // 숫자 한 자리씩 추출하여 char로 변환
                num /= 10;
            }
            // 남은 앞부분을 '0'으로 채우기
            while (i >= 0) {
                charBuffer[i--] = '0';
            }
        }

        // 팰린드롬 검사
        for (int j = 0; j < originalLength / 2; j++) {
            if (charBuffer[j] != charBuffer[originalLength - 1 - j]) {
                return false; // 하나라도 다르면 팰린드롬이 아닙니다.
            }
        }
        return true; // 모든 문자가 일치하면 팰린드롬입니다.
    }

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder sb = new StringBuilder(); // 결과값을 효율적으로 저장하기 위한 StringBuilder

        // charBuffer를 미리 한 번만 할당합니다. 최대 9자리 숫자에 대응
        char[] charBuffer = new char[9];

        while (true) {
            String line = br.readLine();
            if (line.equals("0")) { // 입력이 "0"이면 종료합니다.
                break;
            }

            int originalLength = line.length(); // 원래 숫자의 길이 (자리수 유지 중요)
            long currentNumber = Long.parseLong(line); // 현재 주행 거리계 숫자를 long 타입으로 변환

            int distance = 0; // 주행 거리 초기화

            while (true) {
                // isPalindrome 메서드에 currentNumber와 originalLength, 그리고 charBuffer를 전달합니다.
                // 이 메서드 내에서 charBuffer를 재사용하여 String 객체 생성을 막습니다.
                if (isPalindrome(currentNumber, originalLength, charBuffer)) {
                    sb.append(distance).append("\n"); // 팰린드롬이면 거리 저장 후 반복 종료
                    break;
                }

                currentNumber++; // 팰린드롬이 아니면 숫자를 1 증가시킵니다.
                distance++; // 주행 거리도 1 증가시킵니다.
            }
        }

        System.out.print(sb.toString()); // 모든 결과를 한 번에 출력합니다.
        br.close();
    }
}

마무리

코드와 설명이 부족할수 있습니다. 코드를 보시고 문제가 있거나 코드 개선이 필요한 부분이 있다면 댓글로 말해주시면 감사한 마음으로 참고해 코드를 수정 하겠습니다.

profile
Junior backend developer

0개의 댓글