자연수 x
를 y
로 변환하려고 합니다. 사용할 수 있는 연산은 다음과 같습니다.
x
에 n
을 더합니다x
에 2를 곱합니다.x
에 3을 곱합니다.자연수 x
, y
, n
이 매개변수로 주어질 때, x
를 y
로 변환하기 위해 필요한 최소 연산 횟수를 return하도록 solution 함수를 완성해주세요. 이때 x
를 y
로 만들 수 없다면 -1을 return 해주세요.
x
≤ y
≤ 1,000,000n
< y
x | y | n | result |
---|---|---|---|
10 | 40 | 5 | 2 |
10 | 40 | 30 | 1 |
2 | 5 | 4 | -1 |
입출력 예 #1
x
에 2를 2번 곱하면 40이 되고 이때가 최소 횟수입니다.
입출력 예 #2
x
에 n
인 30을 1번 더하면 40이 되고 이때가 최소 횟수입니다.
입출력 예 #3
x
를 y
로 변환할 수 없기 때문에 -1을 return합니다.
출처: 프로그래머스 코딩 테스트 연습, https://programmers.co.kr/learn/challenges
- DFS 활용
dfs(x,count) -> x => 더해지는 값 , count=> 몇번 계산이 이어졌는지
- x값이 y랑 같아지면 리턴
-> 단, count값을 기존 최솟값과 비교해서 더 작다면 최소값 재할당- x>y 라면 그냥 리턴 => 값이 넘어갔기 때문에 계산할 필요가 없음.
- 두개 다 아니라면 DFS반복 (3개)
- dfs(x2,count+1)
2.dfs(x3,count+1)
3.dfs(x+n,count+1)
function solution(x, y, n) {
var answer = -1;
var count = 0;
function dfs(x,count){
if(x===y){
//초기값 잡기
if(answer===-1){
answer = count;
}
else{
if(answer>count) answer = count;
}
return;
}
else if(x>y) return;
else{
dfs(x*2,count+1)
dfs(x*3,count+1)
dfs(x+n,count+1)
}
}
dfs(x,count);
return answer;
}
우선 결과는 무조건 나온다. 단, 시간초과가 나온다. 보통 DFS나 BFS로 풀다가 시간 초과가 나오면 DP를 도전해본다.
dpArr을 y+1개 만큼 생성하고 -1로 채움.
그 후에 dpArr[x] = 0이라고 초기값 설정
- 이제 x~y까지 차례대로 아래 과정 계산 -> i라고 가정
- dpArr[i] === -1 => 패스 (나올 수 없는 수임)
- i + n < y -> n을 더할 수 있는 i라면?
-> dpArr[i+n]이 처음 도달한 값이라면 그전꺼에 +1해서 할당
-> 처음 도달한게 아니라 값이 존재한다면 작은걸로 설정- i 2 , i 3도 이 방법을 똑같이 진행
- 마지막에 dpArr[y]를 리턴
function solution(x, y, n) {
var dpArr = new Array(y+1).fill(-1);
dpArr[x] = 0;
for(var i = x;i<=y;i++){
if(dpArr[i]===-1){
continue;
}
if(i+n<=y){
if(dpArr[i+n]===-1){
dpArr[i+n] = dpArr[i]+1;
}
else{
dpArr[i+n] = dpArr[i+n]>dpArr[i]+1?dpArr[i]+1:dpArr[i+n];
}
}
if(i*2<=y){
if(dpArr[i*2]===-1){
dpArr[i*2] = dpArr[i]+1;
}
else{
dpArr[i*2] = dpArr[i*2]>dpArr[i]+1?dpArr[i]+1:dpArr[i*2];
}
}
if(i*3<=y){
if(dpArr[i*3]===-1){
dpArr[i*3] = dpArr[i]+1;
}
else{
dpArr[i*3] = dpArr[i*3]>dpArr[i]+1?dpArr[i]+1:dpArr[i*3];
}
}
}
return dpArr[y];
}
만약 본인과 같이 dfs를 풀다가 시간초과가 난다면 불필요한 과정을 줄일 수 있는 DP
를 이용해보자.
좋은 풀이 감사합니다 🥹