377. Combination Sum IV

QUESTION

Given an integer array with all positive numbers and no duplicates, find the number of possible combinations that add up to a positive integer target.

Example:

nums = [1, 2, 3]
target = 4

The possible combination ways are:
(1, 1, 1, 1)
(1, 1, 2)
(1, 2, 1)
(1, 3)
(2, 1, 1)
(2, 2)
(3, 1)

Note that different sequences are counted as different combinations.

Therefore the output is 7.

Follow up:

What if negative numbers are allowed in the given array?

How does it change the problem?

What limitation we need to add to the question to allow negative numbers?

THOUGHT I

这道题跟以前的不一样的地方在于只要求给出组合的数目,不要求给出组合,开始的想法是按照以前的做法去做,不过他这里允许出现[1,2,2],[2,1,2],[2,2,1]这样的组合,也就是说可以往回去找数值。

CODE
public class Solution {
    public int combinationSum4(int[] nums, int target) {
        if(nums == null || nums.length == 0 || target == 0)
            return 0;
        List<Integer> temp = new ArrayList<>();
        Arrays.sort(nums);
        return helper(nums,target,temp,0);
    }
    public int helper(int[] nums,int target,List<Integer> temp,int count){
        if(target == 0){
            count++;
            return count;
        }
        if(target < 0)
            return count;
        for(int i = 0;i < nums.length;i++){
            if(nums[i] > target)
                return count;
            target -= nums[i];
            temp.add(nums[i]);
            helper(nums,target,temp,count);
            target += nums[i];
            temp.remove(temp.size() - 1);
        }
        return count;
    }
}
RESULT

超时了。

THOUGHT II
count[target] = sum(count[target - nums[i]]), where 0 <= i < nums.length, and target >= nums[i].

target是由哪些比它小的数组合得到的,举例来说,数组nums为{1,2},target为5,那么count[5] = count[5-1]+count[5-2];和换零钱的思路是一样的,钱的总数是5块,零钱有1块和两块的,那么换五块钱的组合数为换4块钱的组合数加上换3块钱的组合数,【这里真是不好理解】而换三块钱的组合数为换一块钱的组合数加上换两块钱的组合数,换一块钱的组合数为1,换两块钱的组合数为2,所以换三块钱的组合数为3.换四块钱的组合数为换三块钱的组合数加上换两块钱的组合数为3+2=5,所以最后结果为8.

CODE
public class Solution {
    public int combinationSum4(int[] nums, int target) {
        if(target == 0)
            return 1;
        int res = 0;
        for(int i = 0;i < nums.length;i++){
            if(target >= nums[i])
                res += combinationSum4(nums,target - nums[i]);
        }
        return res;
    }
}
result

超时了,递归的方法做的时间复杂度不会算额。。。

THOUGHT II

上面的思路是好的,但是进行了大量的多余计算,比如我已经算出换四块钱的组合数了,但是没有保存下来,结果导致我下次还得去算一遍,所以效率很低。这次我们用一个数组dp来保存已经算出来的结果。

CODE
public class Solution {
    public int combinationSum4(int[] nums, int target) {
        int[] DP  = new int[target + 1];
        DP[0] = 1;
        for(int i = 1;i <= target;i++){
            for(int num : nums){
                if(i >= num)
                    DP[i] += DP[i - num];
            }
        }
        return DP[target];
    }
}
result

time complexity is O(m * n),space complexity is O(m)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值