Leetcode330 - Patching Array(贪心)

题目链接

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,那么:

  1. 如果数组中下一个数字为sum + 1,那么它刚好是我们需要的,我们能够得到数字的新范围是 [1,sum+sum+1)]
  2. 如果数组中下一个数字x小于sum,则它一定能够被拼凑出来,加入数x后,我们能够得到数字的新范围为 [1,sum+x]

否则,我们需要往原来的数组中加入新的元素 sum+1

那么我们为什么要往数组中加入 sum+1 ?首先,sum已经被凑出来了并且他是我们目前能够得到最大的,那么我们下一个就需要加入 sum+1 了;并且,加入sum + 1后, [1,2sum+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;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值