题目要求 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 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?
有一个不包含重复值的正整数数组nums,问从数组中选择几个数,其和为target,这样的数的组合有几种?
思路一:自顶向下的dp 这题本质上需要注意一点,就是我如果需要组成target,那么一定是由nums中的一个值和另一个值的排列组合结果构成的。比如com[4] = com[4-1] + com[4-2] + com[4-1]。通过这一点,我们构成一个递归表达式,但是因为单纯的递归表达式没有计算中间结果,所以会造成大量重复的计算影响效率,所以这里采用dp的思路额外的用数组来记录已经计算过的com结果。比如com[3] = com[2] + com[1], com[2] = com[1],如果没有dp,则需要重复计算com[1]的结果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public int combinationSum4 (int [] nums, int target) { if (nums == null || nums.length < 1 ) { return 0 ; } int [] dp = new int [target + 1 ]; Arrays.fill(dp, -1 ); dp[0 ] = 1 ; return helper(nums, target, dp); } private int helper (int [] nums, int target, int [] dp) { if (dp[target] != -1 ) { return dp[target]; } int res = 0 ; for (int i = 0 ; i < nums.length; i++) { if (target >= nums[i]) { res += helper(nums, target - nums[i], dp); } } dp[target] = res; return res; }
思路二:自底向上dp 1 2 3 4 5 6 7 8 9 10 11 12 13 public int combinationSum4 (int [] nums, int target) { Arrays.sort(nums); int [] combinationCount = new int [target+1 ]; combinationCount[0 ] = 1 ; for (int i = 1 ; i<=target ; i++) { for (int j = 0 ; j<nums.length && nums[j] <= i ; j++) { combinationCount[i] += combinationCount[i - nums[j]]; } } return combinationCount[target]; }