[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;
    }
};

本文转自博客园Grandyang的博客,原文链接:补丁数组[LeetCode] Patching Array ,如需转载请自行联系原博主。

相关文章
|
15天前
|
存储 Go 索引
go语言中的数组(Array)
go语言中的数组(Array)
100 67
|
2月前
|
算法
Leetcode 初级算法 --- 数组篇
Leetcode 初级算法 --- 数组篇
43 0
|
4月前
|
算法
LeetCode第53题最大子数组和
LeetCode第53题"最大子数组和"的解题方法,利用动态规划思想,通过一次遍历数组,维护到当前元素为止的最大子数组和,有效避免了复杂度更高的暴力解法。
LeetCode第53题最大子数组和
|
2月前
|
人工智能 前端开发 JavaScript
拿下奇怪的前端报错(一):报错信息是一个看不懂的数字数组Buffer(475) [Uint8Array],让AI大模型帮忙解析
本文介绍了前端开发中遇到的奇怪报错问题,特别是当错误信息不明确时的处理方法。作者分享了自己通过还原代码、试错等方式解决问题的经验,并以一个Vue3+TypeScript项目的构建失败为例,详细解析了如何从错误信息中定位问题,最终通过解读错误信息中的ASCII码找到了具体的错误文件。文章强调了基础知识的重要性,并鼓励读者遇到类似问题时不要慌张,耐心分析。
|
2月前
|
存储 Java
Java“(array) <X> Not Initialized” (数组未初始化)错误解决
在Java中,遇到“(array) &lt;X&gt; Not Initialized”(数组未初始化)错误时,表示数组变量已被声明但尚未初始化。解决方法是在使用数组之前,通过指定数组的大小和类型来初始化数组,例如:`int[] arr = new int[5];` 或 `String[] strArr = new String[10];`。
95 2
|
2月前
【LeetCode-每日一题】 删除排序数组中的重复项
【LeetCode-每日一题】 删除排序数组中的重复项
23 4
|
2月前
|
索引
Leetcode第三十三题(搜索旋转排序数组)
这篇文章介绍了解决LeetCode第33题“搜索旋转排序数组”的方法,该问题要求在旋转过的升序数组中找到给定目标值的索引,如果存在则返回索引,否则返回-1,文章提供了一个时间复杂度为O(logn)的二分搜索算法实现。
24 0
Leetcode第三十三题(搜索旋转排序数组)
|
2月前
|
存储 JavaScript 前端开发
JavaScript Array(数组) 对象
JavaScript Array(数组) 对象
29 3
|
2月前
|
算法 C++
Leetcode第53题(最大子数组和)
这篇文章介绍了LeetCode第53题“最大子数组和”的动态规划解法,提供了详细的状态转移方程和C++代码实现,并讨论了其他算法如贪心、分治、改进动态规划和分块累计法。
70 0
|
2月前
|
C++
【LeetCode 12】349.两个数组的交集
【LeetCode 12】349.两个数组的交集
19 0