题目
你正在玩一个整数游戏。从整数 1 开始,期望得到整数 target 。
在一次行动中,你可以做下述两种操作之一:
递增,将当前整数的值加 1(即, x = x + 1)。
加倍,使当前整数的值翻倍(即,x = 2 * x)。
在整个游戏过程中,你可以使用 递增 操作 任意 次数。但是只能使用 加倍 操作 至多 maxDoubles 次。
给你两个整数 target 和 maxDoubles ,返回从 1 开始得到 target 需要的最少行动次数。
题解
- 循环写法
class Solution {
public int minMoves(int target, int maxDoubles) {
int ans = 0;
while(target != 1){
//若target是双数,且还能够除以2,除以2,递归一次
if(target %2 == 0 && maxDoubles != 0){
target = target/2;
maxDoubles--;
ans++;
}
else{
if(maxDoubles ==0) //如果maxDouble为零,后面就不循环了,直接得到答案。
return ans+target-1;
target--;
ans++;
}
}
return ans;
}
}
- 递归写法
class Solution {
public int minMoves(int target, int maxDoubles) {
//递归终止条件
if(target ==1 || maxDoubles ==0)
return target-1;
//当target为双数时,除以2,maxDouble次数减一,然后递归调用1次
//当target为单数时,减1,然后递归调用1次
return target %2 == 0 ? minMoves(target/2,maxDoubles-1)+1:minMoves(target-1,maxDoubles)+1;
}
}
思路
- 这是非递归的写法
- 反向推导法,用到了类似贪婪算法的规则?只要能除以2,就除以2,因为越晚除,数字target下降得越慢。
- 当target变成1的时候,终止循环。
- 还可以用递归写法。