Post

백준 2577번

백준 2577번

[Bronze II] 숫자의 개수 - 2577

문제 링크

성능 요약

메모리: 14036 KB, 시간: 104 ms

분류

수학, 구현, 사칙연산

제출 일자

2026년 3월 5일 11:18:02

문제 설명

세 개의 자연수 A, B, C가 주어질 때 A × B × C를 계산한 결과에 0부터 9까지 각각의 숫자가 몇 번씩 쓰였는지를 구하는 프로그램을 작성하시오.

예를 들어 A = 150, B = 266, C = 427 이라면 A × B × C = 150 × 266 × 427 = 17037300 이 되고, 계산한 결과 17037300 에는 0이 3번, 1이 1번, 3이 2번, 7이 2번 쓰였다.

입력

첫째 줄에 A, 둘째 줄에 B, 셋째 줄에 C가 주어진다. A, B, C는 모두 100보다 크거나 같고, 1,000보다 작은 자연수이다.

출력

첫째 줄에는 A × B × C의 결과에 0 이 몇 번 쓰였는지 출력한다. 마찬가지로 둘째 줄부터 열 번째 줄까지 A × B × C의 결과에 1부터 9까지의 숫자가 각각 몇 번 쓰였는지 차례로 한 줄에 하나씩 출력한다.

코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
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 A = Integer.parseInt(br.readLine());
        int B = Integer.parseInt(br.readLine());
        int C = Integer.parseInt(br.readLine());
        int[] line = new int[10];

        String sum = String.valueOf(A * B * C);


        for (int i = 0; i < sum.length(); i++) {
            for (int j = 0; j <= 9; j++) {

               if (sum.charAt(i) == (char)(j + '0')) {

                   line[j]++;

               }

            }
        }

        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < 10; i++) {

            sb.append(line[i]).append("\n");

        }

        System.out.println(sb);

    }
}

1. 초기 접근 방식

  • 초기 접근: 0부터 9까지 숫자의 개수를 세기 위해 크기가 10인 배열(line)을 만들고, A * B * C의 결과를 문자열(String)로 변환하여 확인하는 방식을 떠올림.
  • 로직 구상: 이중 for문을 사용하여 문자열의 각 자리(charAt)와 0~9 문자를 일일이 비교한 뒤, 일치하면 배열의 인덱스 값을 증가시키고 StringBuilder를 통해 출력함.

2. AI 튜터 활용

질문 : ‘기존 로직(이중 루프 + 문자열 변환)보다 더 빠르고 효율적으로 하는 법이 있을까?’라고 질문.

AI의 답변 :

  1. 내부 반복문 제거 (시간 최적화) 이중 루프를 돌며 0~9를 일일이 비교할 필요 없이, 문자에서 '0'을 빼는 연산(charAt(i) - '0')을 활용하면 곧바로 정수형 인덱스를 얻을 수 있습니다. 이를 통해 O(N*10)의 연산을 O(N)으로 대폭 줄일 수 있습니다.

  2. 문자열 변환 생략 (메모리 최적화) String.valueOf()는 새로운 객체를 메모리에 할당합니다. 객체 생성 없이 A * B * C를 정수형 변수에 담아둔 채, % 10(나머지)과 / 10(몫) 연산을 while문으로 반복하면 각 자릿수를 직접 추출할 수 있어 메모리를 절약합니다. 추가로, 결과가 0인 엣지케이스를 방어하기 위해 조건 검사를 나중에 하는 do-while문 구조를 채택할 수 있습니다.

1번 질문에 대해 수정한 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
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 A = Integer.parseInt(br.readLine());
        int B = Integer.parseInt(br.readLine());
        int C = Integer.parseInt(br.readLine());
        int[] line = new int[10];

        String sum = String.valueOf(A * B * C);


        for (int i = 0; i < sum.length(); i++) {

            int num = sum.charAt(i) - '0';
            line[num]++;

        }

        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < 10; i++) {

            sb.append(line[i]).append("\n");

        }

        System.out.println(sb);

    }
}

2번 질문에 대해 수정한 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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 A = Integer.parseInt(br.readLine());
        int B = Integer.parseInt(br.readLine());
        int C = Integer.parseInt(br.readLine());
        int[] line = new int[10];

        int sum = A * B * C;
        int R = 0;

        StringBuilder sb = new StringBuilder();

       do {

            R = sum % 10;
            sum = sum / 10;

            line[R]++;

        }  while (sum > 0);

        for (int i = 0; i <= 9; i++) {

            sb.append(line[i]).append("\n");

        }

        System.out.println(sb);

    }
}

얻은 깨달음 :

  • 불필요한 이중 루프는 아스키코드의 특성(-'0')을 활용해 배열 인덱스에 직접 매핑하여 제거할 수 있음.
  • 무조건 String으로 변환하기보다 수학적 연산(%, /)만으로도 자릿수를 분리하는 것이 메모리 최적화에 유리함.
  • 로직이 특정 엣지케이스(sum == 0)에서 실행되지 않을 때, 무조건 1회 실행을 보장하는 do-while문을 적절히 활용할 수 있음.
This post is licensed under CC BY 4.0 by the author.