今天的困难挑战失败,开始写了O(n^2)级别的,建立存储空间超出范围了,题解空间复杂度O(1)真的是牛
原题目
给定一个已排序的正整数数组 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
著作权归领扣网络所有。
失败原因
未进行数学推导,直接暴力求解
推导步骤
- 注意题目写了是升序排列
- 如果现有的数的任意几个组成的和可以达到这个值,这个值可以不用插入,比如[1,2] 3,因为1+2=3,所以3这个值可以不用插入
- 对于任意1到n的数,这道题有两种处理方式,
- 没有,补充值,并跳到2倍的位置
- 有,但是重复了,那么最大值就加上这个值
为什么乘以2?对于数字1…n,求和可以达到(1+n)*n/2,为什么不跳到这个数呢?
因为我们的数字不是全的,我们只能保证在循环到n时,前面的和能达到n-1,所以此时达到的最大和可以为2n-1,下一个需要检查的值是2n
为什么要检查重复数字呢?
例子:[1,2,2],5,可以看出2是有重复的,但是重复值同样可以扩展最大值,扩展长度为nums[i],如此例,加入最后一个2后,最大值可扩展到5
补充后,如下:
class Solution {
public int minPatches(int[] nums, int n) {
int patches = 0;
long x = 1;//下一个要检查的数字
int length = nums.length, index = 0;
while (x <= n) {
//存在重复数字,那么长度扩展nums[index]
if (index < length && nums[index] <= x) {
x += nums[index];
index++;
} else {
//不存在,当前x为需要补充的值
patches++;
//此时最大值为2x-1,下一个要检查的是2x
x *= 2;
}
}
return patches;
}
}
贪心是弱项,大概扫了一下,已经看题目的分为几类:
-
脑筋急转弯【这个基本无法训练,看是否警醒】
1568题 使陆地分离的最小条数
45题 跳跃游戏 -
排序类【这个做多了还是可以】
1383题 最大的团队表现值
406 根据身高重建序列 -
数学类
当前这题【这个要有一定的推导能力,比较明确的思路,比较难练,只能多做】
1058 最小化舍入差以满足目标
1663 具有给定数值的最小字符串