题目链接
https://leetcode.com/problems/patching-array/
题意
给出一个序列a[],要求往这个序列中添加最少的数字,使这个序列能组成1到n之间的所有数
思路
算法如下:
记录当前拼凑出的最大数字sum,初始为0。
tot为我们需要添加的元素值,初始化为0。
当 sum<n :
若数组中的元素已经全部用完,tot++,加入的元素 sum+1 ,并且更新sum为 sum+(sum+1) 。
否则如果当前元素x比sum小,那么它一定能够被拼的,更新sum为 sum+x 。
如果当前元素 x==sum+1 ,那么它正是我们下一个需要的元素,更新sum为 sum+x 。
否则,tot++,加入元素 sum+1 ,更新sum为 sum+(sum+1) 。
我们的算法基于这样一个事实:
假设我们已经拼凑出了 [1,sum] 之间的所有数字,并且我们用掉的数字的和是sum,那么:
- 如果数组中下一个数字为sum + 1,那么它刚好是我们需要的,我们能够得到数字的新范围是 [1,sum+(sum+1)] 。
- 如果数组中下一个数字x小于sum,则它一定能够被拼凑出来,加入数x后,我们能够得到数字的新范围为 [1,sum+x] 。
否则,我们需要往原来的数组中加入新的元素 sum+1 。
那么我们为什么要往数组中加入 sum+1 ?首先,sum已经被凑出来了并且他是我们目前能够得到最大的,那么我们下一个就需要加入 sum+1 了;并且,加入sum + 1后, [1,2⋅sum+1] 之间的数都能够被拼出来了。
代码
class Solution {
public:
int minPatches(vector<int>& nums, int n) {
long long sum = 0;
int cur = 0, tot = 0;
while (sum < n) {
if (cur < nums.size() && (sum >= nums[cur] || nums[cur] == sum + 1)) {
sum += nums[cur];
cur++;
} else {
sum <<= 1;
++sum;
++tot;
}
}
return tot;
}
}