Coding Test/SW Expert Academy

[SW Expert Academy] 17299 최소 덧셈 - 자바

lsh2613 2023. 7. 11. 11:17

https://swexpertacademy.com/main/code/problem/problemDetail.do

 

SW Expert Academy

SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!

swexpertacademy.com

문제 풀이

이 문제에 경우 특별한 알고리즘을 필요로 하진 않는다. 조금만 생각한다면 주어진 조건을 쉽게 찾을 수 있다. 먼저 반으로 나눴을 때 합이 최소가 되려면 자릿수가 가장 적어여 한다.
1이 아무리 작은 값이라도 10만의 자리수로 가면 그 밑의 자릿수에서 아무리 9여도 1보다 클 수 없다는 얘기다.
즉, 자릿수를 가장 적게 만들도록 로직을 작성하면 된다.

그럼 어떻게 만들란 말인가??

1. 우선 짝수일 때를 생각해보면 무조건 반띵이다. 조금만 생각하면 알 수 있으니 설명은 생략한다.
2. 그럼 홀수일 때는? 두 가지로 나뉜다.
      a. 왼쪽 서브스트링이 더 긴 경우
      b. 오른쪽 서브스트링이 더 긴 경우

 

2번이 이해가 가지 않는다면 예시를 들어보겠다.
123이 있을 때 반띵을 하려니 정확히 나누어지지 않는다.
왼 쪽이 클 수도 있고 오른쪽이 클 수도 있으니 이 두 경우의 수를 모두 계산한다.
12+3 VS 1+23 따라서 15가 더 작으므로 15를 선택하게 만들면 된다.
위 알고리즘을 코드로 살펴보자.

코드

import java.util.Arrays;
import java.util.Scanner;

import static java.lang.Math.min;

/*
   사용하는 클래스명이 Solution 이어야 하므로, 가급적 Solution.java 를 사용할 것을 권장합니다.
   이러한 상황에서도 동일하게 java Solution 명령으로 프로그램을 수행해볼 수 있습니다.
 */
class Solution
{
    public static void main(String args[]) throws Exception
    {
        Scanner sc = new Scanner(System.in);
        int T = sc.nextInt();

        for(int test_case = 1; test_case <= T; test_case++)
        {
            String str = sc.next();
            // int -> int[]
            int[] num = str.chars().map(c -> c - '0').toArray();
            int len = num.length;
            int half = len / 2;

            int[] subLeft = Arrays.copyOf(num, half);
            int[] subRight = Arrays.copyOfRange(num, half, num.length);
            int sumLeft = sum(subLeft);
            int sumRight = sum(subRight);

            if (num.length % 2 == 0) { //짝수면 무조건 반갈
                System.out.printf("#%d %d\n", test_case, sumLeft + sumRight);
            }
            else { // 홀수일 땐 왼쪽이 긴 배열, 오른쪽이 긴 배열 두 경우가 있으므로
                int[] subLeft2 = Arrays.copyOf(num, half + 1);
                int[] subRight2 = Arrays.copyOfRange(num, half + 1, num.length);
                int sumLeft2 = sum(subLeft2);
                int sumRight2 = sum(subRight2);

                System.out.printf("#%d %d\n", test_case, min(sumLeft + sumRight, sumLeft2 + sumRight2));
            }

        }
    }

    static int sum(int[] arr) {
        int cnt = 1;
        int result = 0;
        for (int i = arr.length-1; i >= 0; i--) {
            result = result + arr[i] * cnt;
            cnt *= 10;
        }
        return result;
    }
}

보이는 바와 같이 홀수일 경우에 대해선 왼쪽 서브스트링의 길이가 더 긴 경우를 고려하는 부분을 추가해주었다.

주석으로 설명해놓았으니 이해하는데 크게 어렵진 않을 것이다.

추가로 int -> int[], string->int[]로 바꾸는 로직이 생각보다 자주 출제되므로 한번 확실하게 이해하고 넘어가는 편이 좋을 것 같다.