백준 다음수 구하기

KIMYEONGJUN·2025년 12월 14일
post-thumbnail

문제

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

첫째 줄에 테스트 케이스의 개수 T(1<=T<=1,000)가 주어진다.
둘째 줄부터 T개 줄에는 각 테스트 케이스가 주어진다.
테스트 케이스는 한 줄로 이루어져 있으며, 수 A이다. A는 최대 80자리 자연수이다.

각 테스트 케이스에 대해서, 한 줄에 하나씩 A의 다음수를 출력한다.
만약, A의 다음수가 없을 때는 BIGGEST를 출력한다.

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

BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); : 대량의 입력을 효율적으로 처리하기 위해 BufferedReader를 사용한다.
StringBuilder sb = new StringBuilder(); : 여러 테스트 케이스의 결과를 한 번에 모아서 출력하기 위해 StringBuilder를 사용한다. 
이는 반복적인 System.out.println() 호출보다 훨씬 효율적이다.
int T = Integer.parseInt(br.readLine()); : 첫 줄에서 테스트 케이스의 개수 T를 읽는다.
테스트 케이스 반복:
for(int t = 0; t < T; t++) { ... } : T번 반복하며 각 테스트 케이스를 처리한다.
숫자 A 처리:
char[] A = br.readLine().toCharArray(); : 입력으로 받은 숫자 A는 최대 80자리이므로 String으로 받은 뒤 char 배열로 변환하여 각 자릿수에 쉽게 접근할 수 있도록 한다. 
n은 A의 길이이다.
Pivot(i) 찾기:
int i = n - 2; : 배열의 뒤에서 두 번째 인덱스부터 시작한다. (마지막 인덱스는 n-1이다).
while(i >= 0 && A[i] >= A[i + 1]) { i--; } : 이 while 루프는 오른쪽에서 왼쪽으로 이동하며 오름차순이 깨지는 첫 번째 위치(i)를 찾는다. 
즉, A[i]가 A[i+1]보다 작은 경우를 찾는 것이다. 
987과 같은 내림차순 숫자열에서는 이 조건을 만족하는 i를 찾을 수 없게 된다.
"BIGGEST" 판별:
if(i == -1) { sb.append("BIGGEST").append("\n"); } : 만약 i가 -1이 되었다면, 이는 숫자 A의 모든 자릿수가 내림차순으로 정렬되어 있다는 뜻이다 (예: 987, 321). 
즉, 현재 A가 해당 자릿수들로 만들 수 있는 가장 큰 숫자이므로 "BIGGEST"를 출력하고 다음 테스트 케이스로 넘어간다.
교환할 숫자(j) 찾기:
int j = n - 1; : 배열의 마지막 인덱스부터 시작한다.
while(A[j] <= A[i]) { j--; } : 이 while 루프는 A[i](pivot)의 오른쪽 부분(A[i+1]부터 A[n-1]까지)에서 A[i]보다 크면서 가장 작은 숫자 A[j]를 찾는다. 
이렇게 해야 전체적으로 A보다 크면서 가장 작은 '다음수'가 된다.
두 숫자(A[i], A[j]) 교환:
char temp = A[i]; A[i] = A[j]; A[j] = temp; : A[i]와 A[j]의 위치를 바꾼다.
Pivot 뒤쪽 부분(Suffix) 뒤집기:
int start = i + 1; int end = n - 1; : i의 바로 다음 위치부터 배열의 끝까지를 부분 배열로 설정한다.
while(start < end) { ... } : 이 while 루프는 A[start]와 A[end]를 교환하며 start는 증가시키고 end는 감소시켜 부분 배열을 뒤집는다. 
이 부분이 중요한데, A[i]를 교환하고 나면 A[i+1]부터 끝까지의 부분은 여전히 내림차순(또는 일부 내림차순)으로 되어 있는다.
이 부분을 뒤집으면 오름차순으로 정렬되는 효과를 내어, 전체 숫자에서 A보다 크면서 가장 작은 다음 순열이 완성된다.
결과 출력:
sb.append(new String(A)).append("\n"); : 완성된 char 배열 A를 String으로 변환하여 StringBuilder에 추가한다. 
각 테스트 케이스마다 개행 문자를 넣어준다.
System.out.print(sb.toString()); : 모든 테스트 케이스가 끝난 후 StringBuilder에 저장된 모든 결과를 한 번에 출력한다.
br.close(); : BufferedReader 리소스를 닫는다.

코드로 구현

package baekjoon.baekjoon_31;

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

// 백준 2697번 문제
public class Main1236 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder sb = new StringBuilder(); // 효율적인 출력을 위해 StringBuilder 사용
        int T = Integer.parseInt(br.readLine()); // 테스트 케이스 개수 T
        for (int t = 0; t < T; t++) {
            char[] A = br.readLine().toCharArray(); // A를 문자 배열로 변환
            int n = A.length;

            int i = n - 2; // 뒤에서 두 번째 인덱스부터 시작
            // 1. 뒤에서부터 오름차순이 깨지는 지점 (i) 찾기
            // A[i] < A[i+1]을 만족하는 가장 큰 i를 찾는다.
            while (i >= 0 && A[i] >= A[i + 1]) {
                i--;
            }

            if (i == -1) { // A[i] < A[i+1]을 만족하는 i가 없는 경우 (모든 자릿수가 내림차순)
                sb.append("BIGGEST").append("\n");
            } else {
                int j = n - 1; // 뒤에서부터 시작
                // 2. A[i]보다 크면서 가장 작은 A[j] 찾기 (A[i+1]부터 끝까지)
                while (A[j] <= A[i]) {
                    j--;
                }

                // 3. A[i]와 A[j] 교환
                char temp = A[i];
                A[i] = A[j];
                A[j] = temp;

                // 4. A[i+1]부터 끝까지의 부분 배열을 오름차순으로 정렬 (뒤집기)
                // A[i+1]부터 n-1까지의 배열을 뒤집으면 오름차순 정렬과 동일한 효과
                int start = i + 1;
                int end = n - 1;
                while (start < end) {
                    char temp2 = A[start];
                    A[start] = A[end];
                    A[end] = temp2;
                    start++;
                    end--;
                }
                sb.append(new String(A)).append("\n"); // char 배열을 String으로 변환 후 추가
            }
        }
        System.out.print(sb.toString()); // 결과 한 번에 출력
        br.close();
    }
}

마무리

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

profile
Junior backend developer

0개의 댓글