一. 题目描述
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
.
二. 题目分析
题目的大意是,给定一个数组nums
和一个数n
,求添加最少的数使得区间[1, n]
中的每个数都可以由数组nums
中元素累加组成。
由于数组已经排序,因此基本的思路是,定义一个整形变量currSum
,假设数组nums目前可以累加的数的范围为[1, currSum)
,如果此时向数组中添加一个元素k
(k <= currSum
)可以将累加的数的范围扩充为[1, currSum + k)
,而题目中要求向数组nums
添加元素的次数最少,因此当且仅当k = currSum
时,累加数的范围可以取到上限[1, 2 * currSum)
。在遍历数组nums
时,有以下两种操作:
- 当数组中有小于等于currSum的元素
nums[index]
时,则利用数组中的元素,同时currSum += nums[index]
; - 若没有,则添加新元素currSum入数组,此时范围扩展至最大,同时令
currSum <<= 1
。
三. 示例代码
#include <iostream>
#include <vector>
using namespace std;
class Solution {
public:
int minPatches(vector<int>& nums, int n) {
int result = 0, index = 0;
// currSum标记了当前数组nums可累加到的最大范围[1, currSum)
for (int currSum = 1; currSum <= n; )
{
// 数组内元素小于currSum时,可累加的sum上限增加为
// currSum + nums[index],然后数组索引值加1
if (index < nums.size() && nums[index] <= currSum)
currSum += nums[index++];
else
{
currSum <<= 1; // 添入元素后,可累加的sum范围加倍
++result;
}
}
return result;
}
};
四. 小结
这种方法并不容易马上想到,对于这一类型的问题,特别需要在纸面上多列举例子,慢慢从中找出规律。