LeetCode 330. Patching Array

         大概题意:给定一个已经排好序的数组,还有一个数n,问你还需要往数组中添加多少个数,才能对于1 到 n 的每一个数a,都存在数组中的若干个数,使得它们的和等于a 。

         这道题我并没有单独完成,我思考了很久,花了挺长的时间进行尝试,依然没有通过这道题。

         一开始困扰我的问题是,怎么判断当前数组里的数是否已经满足了所要的条件呢?假如这里面有m个数,如果我用穷举法来检验,那时间复杂度就是O(2的n次方)。显然太大了,不可能用在这道题里面。就算数据量足够小,要找出要添加几个数还是很困难的。

         之后我发现了,1, 2, 4, 8, ... , 2的m次方(n <= 2 的m次方),能够组成所有1 到 n中的数字。至于为什么,想一下每个数字的二进制表示就很容易清楚了。而这样也是最少的(当然,在不考虑原数组元素的情况下)。于是我在这样的思路下,在原数组中插入数字来补充 1 到 n 的缝隙(即原来的数字不能组成的数)。这样的做法能够通过一些测试样例,但不能通过这道题。

         最后我还是查找了题解。具体的做法也很简单:设当前能够组成的数为1 ~ curMax。每一步主要考虑着两个问题:现在是否应该取剩余数组中的数?如果不应该,又应该往数组里添加什么数字呢?

         关于第一个问题,设剩余数组元素中的最小值为s,如果s大于curMax + 1,那我们就不能取,因为curMax + 1 ~ s - 1 这一段我们无法通过所拥有的元素组合得到。也就是说,当s 小于等于curMax 的时候,我们应该取。

         第二个问题,应该往数组里添加curMax + 1,这样1 ~ 2*curMax + 1 的数我们都能得到了。

         我从这个题的做法中得到了一些启发:我做这道题的时候,主要的思路是“我该往数组中添加多少数字、什么数字”;但题解的思路是“什么时候可以用到这些数组中的数字”。方向可以说是完全不相同的。所以说,以后做题的时候,特别是对这种贪心类型的题目,换一个方向去思考也许会有不同的收获。

         代码如下,设数组大小为m,时间复杂度在最糟糕的情况下为O(m + logn)。注意curMax 可能会超出int的数据范围。

                  

class Solution {
public:
    int minPatches(vector<int>& nums, int n) {
        long long curMax = 0 ;
        int curNum = 0 ;
        int cnt = 0 ;
        
        int p = 0 ;
        int s = nums.size() ;
        
        while (curMax < n) {
        	if (p < s && nums[p] <= curMax + 1) {
        		curMax += nums[p] ; p++ ;
        	}
        	else {
        		curMax += curMax + 1 ;
        		cnt++ ;
        	}
        }
        
        return cnt ;
    }
};

    



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值