上题
给定一个已排序的正整数数组 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] 区间里所有的数。
所以我们最少需要添加一个数字。 示例 2:输入: nums = [1,5,10], n = 20 输出: 2 解释: 我们需要添加 [2, 4]。 示例 3:
输入: nums = [1,2,2], n = 5 输出: 0
来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/patching-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
int minPatches(int* nums, int numsSize, int n){
int result=0;
long mar=1;
int i=0;
while(mar<=n)
{
if(i<numsSize&&mar>=nums[i])
{
mar+=nums[i];
i++;
}
else
{mar+=mar;
result++;}
}
return result;
}
执行结果:
通过
显示详情
执行用时 :
4 ms
, 在所有 c 提交中击败了
100.00%
的用户
内存消耗 :
7.4 MB
, 在所有 c 提交中击败了
25.00%
的用户
直觉
对于任何缺少的数字,如果我们想要让和能覆盖到它,我们必须添加至少一个小于或等于该数字的数字。否则,将无法覆盖到。想想象你要给一个人 xx
分钱的零钱,但你没有足够的硬币。你肯定会需要面额小于或者等于 xx 的硬币。算法
假设 miss 是缺少的数字中最小的,则区间 [1, miss) (左闭右开) 已经被完全覆盖。为了覆盖 miss,我们需要添加某些小于等于
miss 的数字。否则将不可能覆盖到。例如,数组 nums = [1,2,3,8], n = 16。已经覆盖到的数字有区间 [1, 6] 和 [8, 14]。换而言之,7,
15, 16 没有覆盖到。如果你加的数字大于 7,则 7 依然覆盖不到。假设我们添加的数字是 xx,则区间 [1, miss) 和 [x, x + miss) 均被覆盖到。由于我们知道 x <=
miss,这两个区间必然覆盖了区间 [1, x + miss)。我们希望能够尽可能选择大的
xx,这样覆盖的范围就可以尽可能大。因此,最好的选择是 x = miss。在覆盖到 miss 后,我们可以重新计算覆盖范围,查看新的最小的缺少数字。然后加上该数字。重复操作直到全部数字都被堵盖到。
下面是这个贪心算法的流程:
- 初始化区间 [1, miss) = [1, 1) = 空
- 每当 n 没有被覆盖
- 若当前元素 nums[i] 小于等于 miss 将范围扩展到 [1, miss + nums[i]) 将 i 增加 1
- 否则 将 miss 添加到数组,将范围扩展到 [1, miss + miss) 增加数字的计数
- 返回增加数字的数目
作者:LeetCode
链接:https://leetcode-cn.com/problems/patching-array/solution/an-yao-qiu-bu-qi-shu-zu-by-leetcode/
来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。