백준 2231 문제 <브루트포스>

Frog Lemon·2024년 8월 19일
0

알고리즘

목록 보기
8/20
post-thumbnail

문제

어떤 자연수 N이 있을 때, 그 자연수 N의 분해합은 N과 N을 이루는 각 자리수의 합을 의미한다. 어떤 자연수 M의 분해합이 N인 경우, M을 N의 생성자라 한다. 예를 들어, 245의 분해합은 256(=245+2+4+5)이 된다. 따라서 245는 256의 생성자가 된다. 물론, 어떤 자연수의 경우에는 생성자가 없을 수도 있다. 반대로, 생성자가 여러 개인 자연수도 있을 수 있다.

자연수 N이 주어졌을 때, N의 가장 작은 생성자를 구해내는 프로그램을 작성하시오.

입력

첫째 줄에 자연수 N(1 ≤ N ≤ 1,000,000)이 주어진다.

출력

첫째 줄에 답을 출력한다. 생성자가 없는 경우에는 0을 출력한다.

예제 입력 1

216

예제 출력 1

198


풀이

우선 문제를 해결하기 위해 제가 생각한 조건을 정리하였습니다.

  • 1번 조건 : 1부터 주어진 입력값까지 모든 경우의수를 구해야한다.
  • 2번 조건 : 만족하는 결과(최소 생성자)가 나올시 출력후 프로그램을 종료한다.
  • 3번 조건 : 현재 숫자의 각자리수를 분리하는 방법이 필요하다.

조건 해결

  • 1번 조건 : 반복문을 통해 1 부터 N까지 숫자를 증가시킵니다.
  • 2번 조건 : 만약 최소생성자를 찾을 시 메서드안에서 return을 통해 중지합니다.
  • 3번 조건 : 문자열은 charAt메서드를 통해 각 자리수를 분리할 수 있다. 그리고 문자열이 숫자로 이루어져있다면, char형 '0'을 빼줌으로서 해당자리의 숫자를 구할수 있습니다.

위에는 아스키코드 표입니다.

예를들어 숫자 59를 입력받았다고 가정하겠습니다. 현재 우리는 charAt메서드를 통해 문자(character)형 59를 얻었습니다. 아스키코드표에서 문자 5, 9, 0을 확인하면 10진수 48,53,57 과 같다는걸 확인할 수 있습니다.

char형 '5' - '0'은 53 - 48 과 같기때문에 정수형 5가 나오고
char형 '9' - '0'은 57 - 48 과 같기때문에 정수형 9가 나오게 됩니다.

문자 '0'을 빼면 아스키(ASCII) 값이 나오는 이유는, 자바에서 문자형(char)은 사실상 숫자로 표현되기 때문입니다. 모든 문자는 컴퓨터 내부에서 숫자로 저장되며, 이 숫자는 아스키 코드 값을 나타냅니다.


코드

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));
        int N = Integer.parseInt(br.readLine());
        br.close();

        int result = searchConstructor(N);
        System.out.println(result);
    }

    //최소 생성자 구하는 메서드
    static int searchConstructor(int N){
        //1부터 입력받은 N까지 반복
        for(int i=1 ; i<=N ; i++){

            //현재 숫자 i를 문자열로 바꾸기
            String num =  String.valueOf(i);

            //최소 생성자 변수
            int minConstructor = 0;
            //각 자리수의 합 변수
            int digitSum = 0;

            //입력한 숫자의 각자리수를 digitSum변수에 담기
            for(int j=0 ; j<num.length() ;  j++){
                //숫자를 charAt메서드로 나누어 문자0을 빼주면 정수형 숫자로 전환됨
                digitSum += num.charAt(j) - '0';
            }

            //만약  i(현재숫자) + digitSum(각자리수의 합) = N(입력값) 이라면 최소 생성자 설정
            if(digitSum+i == N){
                minConstructor = i;
                return  minConstructor;
            }
        }
        return 0;
    }
}

결과


후기😢
37분전에 푼것이 현재 다시 제가 해결한 코드인데 , 8달전 코드와 비교해보면 코드길이와 메모리 차이가많이 난다는것을 알 수 있습니다. 다시한번 마음을 다 잡고 타 블로그 분들의 글을 확인해 보았습니다.

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
 
public class Main {
	public static void main(String[] args) throws IOException {
 
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        
		int N = Integer.parseInt(br.readLine());
        
		int result = 0;
 
		
		for(int i = 0; i < N; i++) {
			int number = i;
			int sum = 0;	// 각 자릿수 합 변수 
			
			while(number != 0) {
				sum += number % 10;	// 각 자릿수 더하기
				number /= 10;
			}
			
			// i 값과 각 자릿수 누적합이 같을 경우 (생성자를 찾았을 경우) 
			if(sum + i == N) {
				result = i;
				break;
			}
			
		}
 
		System.out.println(result);
	}
}

출처 https://st-lab.tistory.com/98


이분은 문자열을 하나씩 나누어 처리한것이 아니라, 정수형으로 처리하며 별도의 메서드 없이 연산으로 문제를 해결하셨습니다..!!!👍

예를 들어, i가 123이라면:

첫 번째 반복에서 sum은 3 (123 % 10)이 되고, number는 12 (123 / 10)가 됩니다.
두 번째 반복에서 sum은 5 (12 % 10)가 되고, number는 1 (12 / 10)이 됩니다.
세 번째 반복에서 sum은 6 (1 % 10)이 되고, number는 0 (1 / 10)이 됩니다.

문제를 맞췄다고 안도할게 아니라 , 좀 더 효율적인 코드를 구상하도록 노력해야겠습니다 😊 좋은 코드 감사합니다!

profile
노력과 끈기를 추구합니다. 레몬이 좋아!

0개의 댓글