1 题目:得到整数零需要执行的最少操作数
官方标定难度:中
给你两个整数:num1 和 num2 。
在一步操作中,你需要从范围 [0, 60] 中选出一个整数 i ,并从 num1 减去 2i + num2 。
请你计算,要想使 num1 等于 0 需要执行的最少操作数,并以整数形式返回。
如果无法使 num1 等于 0 ,返回 -1 。
示例 1:
输入:num1 = 3, num2 = -2
输出:3
解释:可以执行下述步骤使 3 等于 0 :
- 选择 i = 2 ,并从 3 减去 22 + (-2) ,num1 = 3 - (4 + (-2)) = 1 。
- 选择 i = 2 ,并从 1 减去 22 + (-2) ,num1 = 1 - (4 + (-2)) = -1 。
- 选择 i = 0 ,并从 -1 减去 20 + (-2) ,num1 = (-1) - (1 + (-2)) = 0 。
可以证明 3 是需要执行的最少操作数。
示例 2:
输入:num1 = 5, num2 = 7
输出:-1
解释:可以证明,执行操作无法使 5 等于 0 。
提示:
1 < = n u m 1 < = 1 0 9 1 <= num1 <= 10^9 1<=num1<=109
− 1 0 9 < = n u m 2 < = 1 0 9 -10^9 <= num2 <= 10^9 −109<=num2<=109
2 solution
如果 k 次可以完成的话则有:
n u m 1 = ∑ j = 1 k 2 i j + k ∗ n u m 2 num_1 = \sum_{j = 1}^{k}2^{i_j} + k * num_2 num1=j=1∑k2ij+k∗num2
所以如果每次用 n u m 1 num_1 num1 减去 n u m 2 num_2 num2 ,如果第 k 次剩余的数 m 能被 k 个2 的次方表示,则 k 就是答案。那怎么确定是否可以呢?这要求此时的 m 的二进制中最多有 k 个 1 并且 m 还要大于等于 k。
代码
class Solution {/** num1 = sum(2**i) + k * num2*/
public:int makeTheIntegerZero(int num1, int num2) {long long y = num1;for (int i = 1;; i++) {y -= num2;if (y < i) return -1;long long x = y;int c = 0;for (; x; x >>= 1) c += x & 1;if (c <= i && c ) return i;}}
};