本文涉及知识点
C++贪心
数论:质数、最大公约数、菲蜀定理
LeetCode991. 坏了的计算器
在显示着数字 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
贪心 数量
情况一:start 等于target。直接返回0。
情况二:start > target。
令最近解为start 、i1 ⋯ \cdots ⋯ i2 target。
性质一:target 只会出现一次,且在最后,否则提前结束。
性质二:不会有数小于target。 假设i2是第一个小于target的数,它的前一个数是i1。由于i1 > target ,故i1-1 >= target,与假设矛盾;
i12 > target2 >= target,也与假设矛盾。
性质三:不会出现乘以2。令最后一个乘法是i1乘以2是i2。根据性质一性质二,i1> target。i1减到target比i1*2减少到target需要的次数少得多。
总结:返回 start - target。
情况三:start < target
令start 最少乘以2 m次后,大于等于target。令 x = start × \times × 2m- target
如果x的第0位(最低位)是1,乘2 m次后,减1。
如果x的第1位 是1,乘2 m-1次后,减1。
即:x 0到m-1位的1,可以一次减掉。其它的乘2之前,一次可以减少 2m。
代码
核心代码
class Solution {
public:
int brokenCalc(int startValue, int target) {
if (startValue > target) { return startValue- target; }
int m = 0;
for (; startValue < target; startValue*=2, m++);
int x = startValue - target;
int ans = 0;
for (int i = 0; i < m; i++) {
if ((1 << i) & x) {
x -= (1 << i);
ans++;
}
}
return m+ ans + x / (1 << m);
}
};
单元测试
int startValue, target;
TEST_METHOD(TestMethod11)
{
startValue = 2, target = 3;
auto res = Solution().brokenCalc(startValue, target);
AssertEx(2, res);
}
TEST_METHOD(TestMethod12)
{
startValue = 5, target = 8;
auto res = Solution().brokenCalc(startValue, target);
AssertEx(2, res);
}
TEST_METHOD(TestMethod13)
{
startValue = 3, target = 10;
auto res = Solution().brokenCalc(startValue, target);
AssertEx(3, res);
}
TEST_METHOD(TestMethod14)
{
startValue = 3, target = 3;
auto res = Solution().brokenCalc(startValue, target);
AssertEx(0, res);
}
TEST_METHOD(TestMethod15)
{
startValue = 13, target = 3;
auto res = Solution().brokenCalc(startValue, target);
AssertEx(10, res);
}