题目链接:
题目:
Given a sorted positive integer array nums and an integer n, add/patch elements to the array such that any number in range [1,
inclusive can be formed by the sum of some elements in the array. Return the minimum number of patches required.
n]
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
.
思路:
考虑 1,2 可以表示出1~3
1,2,4 可以表示出1~7
1,2,4,8,..k 可以表示出1~2*k-1
这是因为{1,2,4,8}这些数 转化为二进制{1,10,100,1000},把它们组合相加就相当于能表示出1~1111 之间的数
所以对于给定的n,想要表示出1~n之间所有的数,集合中只要有1、2、4~(n+1)/2就可以了。
那么如果集合如果给定了不是2的幂次方的数是不是就没用了呢? 当然也是有用的。把这个数d添加到集合里 当前可以表示的范围也就扩大为cur+d了
要注意此时必须cur>=d否则当前集合不一定能表示出1~cur+d。如果cur<d,此时需要添加数让范围扩大,具体可以添加,比当前最高位还多一位的数就可以了,比如当前最高能表示出的数是7(111),我们只需要添加一个8(1000),就能让表示范围扩大一倍。
算法:
public int minPatches(int[] nums, int n) { long cur = 1; int count = 1,i=0; while(cur<=n){ if(i<nums.length&&nums[i]<=cur){ cur+=nums[i]; i++; }else{ count++; cur= cur*2; } } return count; }