题目描述
给定一个已排序的正整数数组 nums,和一个正整数 n 。从 [1, n] 区间内选取任意个数字补充到 nums 中,使得 [1, n] 区间内的任何数字都可以用 nums 中某几个数字的和来表示。请输出满足上述要求的最少需要补充的数字个数。
样例描述
示例 1:
输入: nums = [1,3], n = 6
输出: 1
解释:
根据 nums 里现有的组合 [1], [3], [1,3],可以得出 1, 3, 4。
现在如果我们将 2 添加到 nums 中, 组合变为: [1], [2], [3], [1,3], [2,3], [1,2,3]。
其和可以表示数字 1, 2, 3, 4, 5, 6,能够覆盖 [1, 6] 区间里所有的数。
所以我们最少需要添加一个数字。
思路
贪心 + 分类讨论
- 考虑当前的数ai和x之间的关系,分类讨论如下:
- 如果ai小于等于x,数组的数都加上ai以后的范围就是[0, ai + x),这种情况不需要补数,直接用数组里面的数。如果ai大于x的话,直接加上ai会导致中间出现空缺(x没有被表示),所以是直接补上x,让范围变成2x。
- 贪心题目思路具有跳跃性,背过即可。
- 防止溢出数据范围,用long来表示。
参考AcWing题解这篇
代码
class Solution {
public int minPatches(int[] nums, int n) {
long x = 1, res = 0;
int i = 0;
//假设[0, x)是已经可以表示的
while (x <= n) {
//如果小于x的话,直接补上数组里面的数nums[i]
if (i < nums.length && nums[i] <= x) x += nums[i ++ ];
else {
x += x; //否则补充新的数x,统计结果加一
res ++;
}
}
return (int)res;
}
}