330. Patching Array

Given a sorted positive integer array nums and an integer n, add/patch elements to the array such that any number in range [1, n] inclusive can be formed by the sum of some elements in the array. Return the minimum number of patches required.
Example 1:

Input: nums = [1,3], n = 6
Output: 1 
Explanation:
Combinations of nums are [1], [3], [1,3], which form possible sums of: 1, 3, 4.
Now if we add/patch 2 to nums, the combinations are: [1], [2], [3], [1,3], [2,3], [1,2,3].
Possible sums are 1, 2, 3, 4, 5, 6, which now covers the range [1, 6].
So we only need 1 patch.

Example 2:

Input: nums = [1,3], n = 6
Output: 1 
Explanation:
Combinations of nums are [1], [3], [1,3], which form possible sums of: 1, 3, 4.
Now if we add/patch 2 to nums, the combinations are: [1], [2], [3], [1,3], [2,3], [1,2,3].
Possible sums are 1, 2, 3, 4, 5, 6, which now covers the range [1, 6].
So we only need 1 patch.

Example 3:

Input: nums = [1,2,2], n = 5
Output: 0

This is the right greedy solution with C++

int minPatches(vector<int>& nums, int number)
{
    long long cur = 0, count = 0, i = 0;
    while (cur < number)
    {
        if (i < nums.size() && cur + 1 >= nums[i])cur += nums[i++];
        else { cur += (cur + 1); count++; cout << cur << endl; }
    }
    return count;
}

We want to get all numbers in the [1, number] as well as add as less numbers as possible.
The solution we can easily think of is finding all numbers that could be formed by some elements of the vector nums, then add those not included in the range of [1, number] into the vector nums.
Then I get the following solution which just passed six test cased with a Time Limit Exceed, which make feel extremely uncomfortable
I get through from 1 to number with i, and judge whether i belongs to the vector nums. If it does, I just continue, else I used greedy search to find whether i can be formed by nums's some elements. Firstly, by a binary search, i find the right position j that i should be inserted into nums at by ascending order. Then the consequence by judging whether i can be formed by num's some elements with greedy algorithm will decide to adding a new element into nums or do nothing.

//We design a function to find the right position some number should be inserted at by ascending order.
//Binary search should be a great choice.
//And we should be clear there is no possibility number equals any element of nums.
int rightposition(vector<int>& nums, int number)
{
    //The variable n is the size of nums.
    int n = nums.size();
    //We just return result if it's one of the following situations.
    if (n == 0 || number < nums[0])return 0;
    if (number > nums[n - 1])return n;
    int start = 0, end = n, mid = 0;
    while (start < end)
    {
        int mid = (start + end) / 2;
        if (number < nums[mid])end = mid;
        else start = mid + 1;
    }
    return start;
}
int minPatches(vector<int>& nums, int n)
{
    //We put all the elements of nums into the set se so that we can judge whether some number exists in the nums quackly.
    unordered_set<int> se;
    for (int i = 0; i < nums.size(); i++)se.insert(nums[i]);
    int count = 0;
    for (int i = 1; i <= n; i++)
    {
        //Firstly, if i is included by se, then we continue.
        if (se.find(i) != se.end())continue;
        //If i doesn'y belong to se, then we find the right if we want to insert i into nums
        int right = rightposition(nums, i);
        //We use as many element of nums to make up i, which is called greedy algorithm.
        int j = right, number = i;
        while (j >= 0)
        {
            if (number < nums[j]) { j--; continue; }
            number -= nums[j--];
            if (number == 0)break;
        }
        //If number doesn't equal 0, which means we can't use the elements of nums to make up number, then we put number into nums by ascending order.
        if (number != 0)
        {
            se.insert(i);
            nums.insert(nums.begin() + right, i);
            count++;
        }
    }
    return count;
}

Can’t believe it, huh…..
Now, Let make the first solution clear. Supposing we have ensured that any number from 1 to A can be formed by the elements of nums whose index is in the range[0, i], and what number can we get if we use the elements of nums between index 0 and index i + 1. The answer is clearly 1 to A and nums[i + 1]) to (A + nums[i + 1]), which can be combined into (1, A + nums[i + 1]) if A + 1 >= nums[i + 1], in another situation, A + 1 < nums[i + 1], it means we can’t get A + 1 from index 0 to i + 1, and the nums is sorted by ascending order, which is the precondition of the problem, so we must add a new number whose value equals A + 1 to get A + 1. Then we get the following solution which is shown in the front of the blog.

int minPatches(vector<int>& nums, int number)
{
    long long cur = 0, count = 0, i = 0;
    while (cur < number)
    {
        if (i < nums.size() && cur + 1 >= nums[i])cur += nums[i++];
        else { cur += (cur + 1); count++; cout << cur << endl; }
    }
    return count;
}

http://www.sunshangyu.top/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值