[LeetCode]Patching Array

题目: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:
nums = [1, 3]n = 6
Return 1.

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:
nums = [1, 5, 10]n = 20
Return 2.
The two patches can be [2, 4].

Example 3:
nums = [1, 2, 2]n = 5
Return 0.

题目:

给定一个递增数组和正整数n,找到最少的缺失的数字,使得使用递增数组中的数字和它们的和能包含[1,n]中的所有数字。

思路:

看似复杂实际上很简单,只要能够发现,任何数字int型数字可以使用32位二进制表示,如果在递增的数组中包含所有的二进制的位数对应的数(1,2,4,8,16,...,1024,...)就必然能表示出[1,n]中的所有数字。

进一步我们可以发现当有这样的情况发生时,则必然需要补充数字:

当前k个数的和小于第k+1个数时,其前k个数的和 + 1的数字必须要补充,类似二进制中进位的思想。

这样实际上只需要不停地求前n项和,在和下一个数字比较就能知道那些数字需要补充。

/**
在[1,n]之间的任何一个数i的二进制形式是由01组成,所以可以使用1,2,4,...的和来组成i;
因此,只需要判断数组中的元素有没有1,2,4,...或能组成上面这些数的数组合。
**/
int LeetCode::minPatches(vector<int>& nums, int n){
    long long m = 1;
    int i = 0, patch = 0;//统计patch的数量
    while (m <= n){
        if (i < nums.size() && nums[i] <= m){
            m += nums[i++];//如果nums[i] == m时,m翻倍;反之m会增加nums[i]的大小;经验可知,只要有1,2以及(n,2n)之间的数k可以得到2n。
        }
        else{//m在nums中不存在,或者数组的数值不够
            m <<= 1;
            ++patch;
        }
    }
    return patch;
}

其中,注意

m <<= 1;

补充了元素之后前n项和还要加上补充的元素的值。这里之间变成两倍。

原文地址:https://www.cnblogs.com/yeqluofwupheng/p/7041478.html