2 minute read



문제 풀이


이번 문제는 동적 계획법(DP)을 통해 풀 수 있다.

처음엔 단순히 재귀를 통해 xn, x2, x*3 경우별로 재귀 호출하여 y가 되는 순간의 최소 깊이를 반환하는 방식으로 풀었으나 시간초과가 발생했다.

재귀 코드 - 오답(시간초과 발생)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Solution {
    static int answer;
    public int solution(int x, int y, int n) {
        answer = Integer.MAX_VALUE;
        recursion(x, y, n, 0);
        if(answer == Integer.MAX_VALUE) {
            answer = -1;
        }
        return answer;
    }
    
    public static void recursion(int x, int y, int n, int depth) {
        if(x > y) {
            return;
        }
        if(x == y) {
            answer = Math.min(answer, depth);
        }
        recursion(x+n, y, n, depth+1);
        recursion(x*2, y, n, depth+1);
        recursion(x*3, y, n, depth+1);
    }
}


아이디어 도출

그렇다면 어떻게 시간초과를 줄일 수 있을까? 완전탐색을 하지 않고 효율적인 방법이 없는지를 고민해보니 DP 테이블에 x가 y로 변환되는 최소 연산횟수를 갱신해가며 접근하는 방법으로 풀 수 있다고 판단하여 DP를 이용해 풀 수 있었다.

DP를 이용한 아이디어를 살펴보자.

  1. y만큼의 크기를 가지는 DP 테이블을 선언하고 x부터 y까지 순회하며 DP 테이블의 값을 갱신한다.
  2. DP 테이블의 값을 갱신하는 경우는 index+n, index2, index3과 같이 3가지 경우로 나누어 DP 테이블의 원소를 기록한다.
  3. 현재 위치의 DP 테이블 값이 변환될 수 없는 수라면 -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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import java.util.*;

class Solution {

    // x와 y의 최대 범위 값을 상수로 활용한다.
    static final int MAX_VALUE = 1_000_000;

    public int solution(int x, int y, int n) {
        
        // DP 테이블을 MAX_VALUE 값으로 초기화한다.
        int[] D = new int[y+1];
        Arrays.fill(D, MAX_VALUE);

        // DP 테이블의 x번째 원소를 0으로 초기화한다.
        D[x] = 0;

        /**
         * DP 테이블에 연산 횟수를 갱신하는 반복문
         * x부터 y까지 순회하면서 x의 값에서 변환할 수 있는 i+n일 경우, i*2일 경우, i*3일 경우를 비교한다.
         * 변환할 수 없는 값이라면 
         * 변환할 수 있는 값일 경우 i번째 연산 횟수에서 1씩 증가한 값과 최솟값을 비교하여 갱신한다.
         */
        for(int i=x; i<=y; i++) {
            
            // 현재 위치의 x값이 y로 변환할 수 없다면 -1로 기록하고 넘어간다.
            if(D[i] == MAX_VALUE) {
                D[i] = -1;
                continue;
            }

            // 연산횟수를 기록한다.
            if(i + n <= y) {
                D[i+n] = Math.min(D[i+n], D[i]+1);
            }
            if(i * 2 <= y) {
                D[i*2] = Math.min(D[i*2], D[i]+1);
            }
            if(i * 3 <= y) {
                D[i*3] = Math.min(D[i*3], D[i]+1);
            }

        }
        
        return D[y];
    }

    public static void main(String[] args) {
        
        Solution sol = new Solution();
        
        int x = 10;
        int y = 40;
        int n = 5;
        
        sol.solution(x, y, n);

    }

}

회고

-



출처

-


  • 해당 문제의 저작권은 문제를 만든이에게 있으며 자세한 내용은 문제 링크에서 참조바랍니다.