https://www.acmicpc.net/problem/1463
1463번: 1로 만들기
첫째 줄에 1보다 크거나 같고, 106보다 작거나 같은 정수 N이 주어진다.
www.acmicpc.net
- 접근
처음에는 while 반복문 돌리면서 3으로 나누기, 2로 나누기, 1빼기 순으로 각 조건을 확인해서 count를 세는 간단한 문제인줄 알았다.
하지만 두번째 테스트 케이스를 보면 10의 경우 10 -> 9 -> 3 -> 1 순으로 3번 만에 만들 수 있지만 위 방식으로 풀게되면 10 -> 5 -> 4 -> 2 -> 1 (2로 나누기 부터 적용되기 때문에) 4번으로 최소 횟수가 안되는 함정이 있다.
다시 접근해보면 메모이제이션을 이용한 재귀를 떠올려볼 수 있다.
- 코드
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
Integer[] arr = new Integer[1000001];
arr[0] = arr[1] = 0;
System.out.println(recur(arr, N));
}
public static int recur(Integer[] arr, int N) {
if (arr[N] == null) {
if (N % 6 == 0) {
arr[N] = Math.min(recur(arr, N - 1), Math.min(recur(arr, N / 3), recur(arr, N / 2))) + 1;
} else if (N % 3 == 0) {
arr[N] = Math.min(recur(arr, N / 3), recur(arr, N - 1)) + 1;
} else if (N % 2 == 0) {
arr[N] = Math.min(recur(arr, N / 2), recur(arr, N - 1)) + 1;
} else {
arr[N] = recur(arr, N - 1) + 1;
}
}
return arr[N];
}
}
- 해설
6으로 나눠떨어지는 경우 3가지 연산 방법 중 최소값을 찾아가야한다.
3으로 나눠떨어지는 경우는 2로 나눌수 없으니 2 나누기를 제외한 2가지 연산 방법 중 최소값을 재귀호출!
2으로 나눠떨어지는 경우도 3으로 나누는 것과 마찬가지!
이외에 나눠떨어지지 않으면 1을 빼는 연산 방법을 마지막으로 재귀호출한다.
- 다른 풀이
재귀 함수 매개변수를 통해 count 값을 넘겨주면서 진행하는 방법이 있다.
- 회고
메모이제이션까지 방법을 생각해냈지만 구현까지 성공하지 못했다.
계속 문제를 풀면서 구현 능력을 키우면 쉽게 구현할 수 있을 것 같다.
시간 복잡도 O(N)...?
공간 복잡도 O(N)
바텀 - 업 방법으로도 구현해보자
- 참고