본문 바로가기

Algorithm/알고리즘 문제

백준 2992번 : 크면서 작은 수

문제


2992번: 크면서 작은 수 (acmicpc.net)

 

2992번: 크면서 작은 수

정수 X가 주어졌을 때, X와 구성이 같으면서 X보다 큰 수 중 가장 작은 수를 출력한다. 수의 구성이 같다는 말은, 수를 이루고 있는 각 자리수가 같다는 뜻이다. 예를 들어, 123과 321은 수의 구성이

www.acmicpc.net

 

아이디어


1. case를 분류해서 조건식으로만 푸는 방법

  • 각 자리수를 index 취급
  • 숫자가 모두 내림차순으로 정렬되어있으면, 더 커질 수 없으므로 0출력
  • 숫자 중에 오름차순으로 정렬된게 있는지 확인, 이는 숫자의 순서를 바꿈으로써 커질 수 있는 위치를 뜻함
  • 오름차순이 발견된 idx 중에서 가장 뒤에 있는 idx를 찾기 = point로 저장
  • point 뒤에 있는 수 중에서 point 해당하는 수보다 크면서 가장 작은 수 구해서 swap
  • swap 하면 그 자리엔 원래 수보다 큰 수가 오게 되므로 이후의 수는 모두 오름차순으로 정렬
  • e.g 1234 => 1243 | 6372 => 6732 | 10044 => 10404 | 27711 => 71127
package biggerSmallest;

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

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String[] s = br.readLine().split("");
        int[] num = new int[s.length];
        for (int i = 0; i <s.length ; i++) {
            num[i] = Integer.parseInt(s[i]);
        }

        // 오름차순이 일어나는 idx 중 가장 마지막 idx를 확인하는 부분
        int point = -1;
        for (int i = 0; i < num.length-1; i++) {
            if(num[i]<num[i+1]){ // 오름차순 발견되었으면 인덱스 갱신
                point = i;
            }
        }
        // System.out.println("point는 " + point);

        int min = 0;
        int minIdx = -1;
        if(point==-1){ // 오름차순이 없는 경우
            System.out.println(0);
        } else {
            // 오름차순이 있는 경우
            // point뒤에 있는 수 중에서 point의 수보다 더 크면서 가장 작은 것 찾기
            for (int i = point+1; i < num.length; i++) {
                if(num[i]>num[point]){
                    if(minIdx==-1){
                        min = num[i];
                        minIdx = i;
                    } else{
                        if(num[i]<min){ // 같으면 더 앞에 있는 것과 바꾸는게 더 숫자가 작아지므로 idx 갱신안함
                            min = num[i];
                            minIdx = i;
                        }
                    }
                }
            }

            // swap
            int t = num[minIdx];
            num[minIdx] = num[point];
            num[point] = t;

            // bubble sort
            for (int i = point+1; i < num.length-1; i++) {
                for (int j = i+1; j < num.length; j++) {
                    if(num[i]>num[j]){
                        int p = num[i];
                        num[i] = num[j];
                        num[j] = p;
                    }
                }
            }

            // print
            for (int i = 0; i < num.length; i++) {
                System.out.print(num[i]);
            }
        }
    }
}

 

2. 순열을 이용해서 푸는 방법

  • 순열을 이용해서 주어진 숫자의 조합으로 만들 수 있는 모든 순서쌍을 구함
  • dept == r 을 만족하여 하나의 순서쌍을 구하는게 종료되면 조건문을 통과하도록 함
  • 조건문 : 원래 값보다 큰 것 중에서 가장 작은 것
  • 전역변수로 min을 만들어줘서 재귀함수 안에서 하나의 공통된 min 값을 사용할 수 있게 함
package biggerSmallestByPermutation;

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

public class Main {
    static int N, origin, min = Integer.MAX_VALUE;
    static int[] arr, out;
    static boolean[] visited;
    public static void main(String[] args) throws IOException {
        // 입력 처리 : String -> int[]
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String s = br.readLine();
        origin = Integer.parseInt(s);
        String[] sarr = s.split("");
        arr = new int[sarr.length];
        for(int i=0; i<sarr.length; i++){
            arr[i] = Integer.parseInt(sarr[i]);
        }

        N = arr.length;
        out = new int[N];
        visited = new boolean[N];

        per(0);
        System.out.println(min == Integer.MAX_VALUE ? 0 : min);
    }

    public static void per(int dept){
        if(dept == N){
            // 배열을 int로 바꾸기
            int outNum = 0;
            for(int i=0; i<arr.length; i++){
                outNum += Math.pow(10,i)*out[i];

            }

            // 기존 수보다 더 크면서 가장 작은 min 구하기
            if(outNum>origin){
                if(outNum<min){
                    min=outNum;
                }
            }
            return;
        }

        for(int i=0; i<N; i++){
            if(visited[i]==false){
                visited[i]=true;
                out[dept] = arr[i];
                per(dept+1);
                visited[i]=false;
            }
        }
    }
}

'Algorithm > 알고리즘 문제' 카테고리의 다른 글

백준 2567번 : 색종이-2  (0) 2023.07.12
백준 10434번 : 행복한 소수  (0) 2023.07.12
백준 2304번 : 창고 다각형  (0) 2023.06.27
백준 5397번 : 키로거  (0) 2023.06.25
백준 1406번 : 에디터  (0) 2023.06.24