[LeetCode] 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.

Credits:
Special thanks to @dietpepsi for adding this problem and creating all test cases.

 

這道題給我們一個有序的正數數組nums,又給了我們一個正整數n,問我們最少需要給nums加幾個數字,使其能組成[1,n]之間的所有數字,注意數組中的元素不能重復使用,否則的話只有要有1,就能組成所有的數字了。這道題我又不會了,上網看到了史蒂芬大神的解法,膜拜啊,這里就全部按他的解法來講吧。我們定義一個變量miss,用來表示[0,n]之間最小的不能表示的值,那么初始化為1,為啥不為0呢,因為n=0沒啥意義,直接返回0了。那么此時我們能表示的范圍是[0, miss),表示此時我們能表示0到miss-1的數,如果此時的num <= miss,那么我們可以把我們能表示數的范圍擴大到[0, miss+num),如果num>miss,那么此時我們需要添加一個數,為了能最大限度的增加表示數范圍,我們加上miss它本身,以此類推直至遍歷完整個數組,我們可以得到結果。下面我們來舉個例子說明:

給定nums = [1, 2, 4, 11, 30], n = 50,我們需要讓[0, 50]之間所有的數字都能被nums中的數字之和表示出來。

首先使用1, 2, 4可能表示出0到7之間的所有數,表示范圍為[0, 8),但我們不能表示8,因為下一個數字11太大了,所以我們要在數組里加上一個8,此時能表示的范圍是[0, 16),那么我們需要插入16嗎,答案是不需要,因為我們數組有1和4,可以組成5,而下一個數字11,加一起能組成16,所以有了數組中的11,我們此時能表示的范圍擴大到[0, 27),但我們沒法表示27,因為30太大了,所以此時我們給數組中加入一個27,那么現在能表示的范圍是[0, 54),已經滿足要求了,我們總共添加了兩個數8和27,所以返回2即可。

 

解法一:

class Solution {
public:
    int minPatches(vector<int>& nums, int n) {
        long miss = 1, res = 0, i = 0;
        while (miss <= n) {
            if (i < nums.size() && nums[i] <= miss) {
                miss += nums[i++];
            } else {
                miss += miss;
                ++res;
            }
        }
        return res;
    }
};

 

下面這種方法跟上面那種方法原理都一樣,稍有不同之處在於真正的patch了nums數組,把需要插入的數字真正的加入了數組中,那么最后用新數組的長度減去原始長度就知道我們加入了幾個數字了。

 

解法二:

class Solution {
public:
    int minPatches(vector<int>& nums, int n) {
        long miss = 1, k = nums.size(), i = 0;
        while (miss <= n) {
            if (i >= nums.size() || nums[i] > miss) {
                nums.insert(nums.begin() + i, miss);
            }
            miss += nums[i++];
        }
        return nums.size() - k;
    }
};

 

參考資料:

https://leetcode.com/discuss/82895/actually-patching

https://leetcode.com/discuss/82822/solution-explanation

 

LeetCode All in One 題目講解匯總(持續更新中...)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM