LeetCode330. Patching Array

来源:互联网 发布:python t 编辑:程序博客网 时间:2024/05/20 19:16

Ptaching 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.

题目大意是,给定一个有序地数组nums,以及一个数n。要求在数组中加入一些数,使得在[1, n]范围内的所有数都能由nums中的一个或一些数通过求和得到。求在数组中加入数字的最小数量。

要解决这道题目,首先明白一个规律:假设当前我们通过数组的前i个数,已经能通过求和覆盖[1, m]内的所有值,那么当我们再利用数组的第i+1个数,即nums[i+1],能得到的范围是什么呢?答案是[1, nums[i+1] + m]。在有了nums[i+1]的基础上,分别加上[1, m]内的所有值即可。

为了更好理解本题的解法,先给出代码实现:

class Solution {public:    int minPatches(vector<int>& nums, int n) {        long missNum = 1, index = 0, toAddN = 0;        while (missNum <= n) {            if (index < nums.size() && nums[index] <= missNum) {                missNum += nums[index];                index++;            }            else {                toAddN++;                missNum *= 2;            }        }        return toAddN;       }};

其中,missNum为代表当前缺失的值,index代表当前数组下标,toAddN表示要加上数的最小的数量。

算法核心思想如下:假设当前我们已经通过nums[0]nums[index-1]中的所有数,获得了范围在 [1, missNum) 的所有值。那么,当我们把下标index-1移到下一位index,将会出现两种情况:
- nums[index] <= missNum。那么,根据我们之前得到的规律,现在可得的的范围,已经可以扩展到[1, missNum + nums[index])。
- nums[index] > missNum。那么我们已经无法通过数组中的和得到missNum这个值了,于是我们需要把这个值加入到数组中,且toAddN计数加一。此时,和的范围已经变成了[1, missNum * 2)。
根据以上规律,我们每扫过nums中的一个数,便能得到一个新的和的范围。当范围值已经覆盖到输入的n的时候,证明添加的数已经得到了要求。

可是,如何证明按照这个算法得到的toAddN一定是最小的呢?原理很简单,当需要在数组中添加一个数时,添加的数越大,和的范围就会相应地扩展到最大。又由于缺失的missNum是无法由前面的数求和得到的,那么此时将missNum添加到数组中,就是能同时满足这两个条件的值。因此添加missNum是最优的做法。

原创粉丝点击