坏了的计算器
在显示着数字 startValue 的坏计算器上,我们可以执行以下两种操作:
双倍(Double):将显示屏上的数字乘 2;
递减(Decrement):将显示屏上的数字减 1 。
给定两个整数 startValue 和 target 。返回显示数字 target 所需的最小操作数。
示例 1:
输入:startValue = 2, target = 3
输出:2
解释:先进行双倍运算,然后再进行递减运算 {2 -> 4 -> 3}.
示例 2:
输入:startValue = 5, target = 8
输出:2
解释:先递减,再双倍 {5 -> 4 -> 8}.
示例 3:
输入:startValue = 3, target = 10
输出:3
解释:先双倍,然后递减,再双倍 {3 -> 6 -> 5 -> 10}.
提示:
- 1 <= startValue, target <= 109
题解
假设目标值为Y,初始值为X。
- 当Y<=X: 结果为 X -Y
- 当Y >X,假设我们已经得到了最短的操作序列为[X,n1, n2,n3,n4…Y] :
- Y为奇数,根据题目限制,倒数第二值一定为偶数 Y + 1, min(Y) = min(Y+1) + 1
- 当Y为偶数时,不妨设Y=2∗T,此时Y可以由T∗2或2∗T−1两种方式得到,若Y由T∗2得到(即倒数第二个中间值为T),那么min(Y)=min(T)+1。若Y由2∗T+1通过减1操作得到,则min(Y)=min(2∗T+1)+1。由于2∗T+1为奇数,由1可知该最优操作序列中倒数第三个数必为2∗T+2=2∗(T+1),故min(Y)=min(2∗T+2)+2。此时2∗T+2为一个偶数,他可以由(T+1)∗2或2∗(T+2)−1−1…得到。我们假设最优的解K使得X→…→(T+K)→2∗(T+K)→2∗(T+K)−1→2∗(T+K)−2→…→Y这样的操作序列最短。仔细观察可以发现,我们可以选择(T+K)这个节点通过K次−1操作得到T然后进行一次乘2操作得到2T=Y,共需要K+1次。而若按照如上的操作序列我们需要2T+2K−2T+1=2K+1次操作。显然Y由−1操作得到的最少操作次数要大于Y由T∗2得到的最少操作次数。因此当Y为偶数时,其前一个中间值必为Y/2。
class Solution {
public:
int brokenCalc(int startValue, int target) {
int step = 0;
while (startValue < target) {
if (target % 2) {
target += 1;
} else {
target = target /2;
}
step ++;
}
return (startValue - target) + step;
}
};