Combination Sum
题目地址:
https://leetcode.com/problems/combination-sum/#/description
题目:
Given a set of candidate numbers (C) (without duplicates) and a target number (T), find all unique combinations in C where the candidate numbers sums to T.
The same repeated number may be chosen from C unlimited number of times.
Note:
- All numbers (including target) will be positive integers.
- The solution set must not contain duplicate combinations.
For example, given candidate set
A solution set is:
[2, 3, 6, 7] and target 7,A solution set is:
[ [7], [2, 2, 3] ]
解题思路:
这道题是典型的backtracking,先排序,当某个元素的值大于target的时候,就要break。这道题还有一个follow up:就是当不能够有重复的解的时候,需要做一下处理。
代码:
public List<List<Integer>> combinationSum(int[] candidates, int target) { List<List<Integer>> rst = new ArrayList<>(); if(candidates == null || candidates.length == 0){ return rst; } Arrays.sort(candidates); List<Integer> list = new ArrayList<>(); helper(rst, list, candidates, target, 0); return rst; } private void helper(List<List<Integer>> rst, List<Integer> list, int[] candidates, int target, int pos) { if(target == 0){ rst.add(new ArrayList<>(list)); return; } for(int i = pos; i <= candidates.length - 1; i++){ if(target < candidates[i]){ break; } list.add(candidates[i]); helper(rst, list, candidates, target - candidates[i], i); list.remove(list.size() - 1); } }
Follow up:
Follow up 2:
Find all possible combinations of k numbers that add up to a number n, given that only numbers from 1 to 9 can be used and each combination should be a unique set of numbers.
Follow up 3:
首先最直接的想法是backtracking:
这里可以用dp来解决:
public List<List<Integer>> combinationSum2(int[] candidates, int target) { List<List<Integer>> rst = new ArrayList<>(); if(candidates == null || candidates.length == 0){ return rst; } Arrays.sort(candidates); List<Integer> list = new ArrayList<>(); helper(rst, list, candidates, target, 0); return rst; } private void helper(List<List<Integer>> rst, List<Integer> list, int[] candidates, int target, int pos) { if(target == 0){ rst.add(new ArrayList<>(list)); return; } for(int i = pos; i <= candidates.length - 1; i++){ if(target < candidates[i]){ break; } if(i != pos && candidates[i - 1] == candidates[i]){ continue; } list.add(candidates[i]); helper(rst, list, candidates, target - candidates[i], i + 1); list.remove(list.size() - 1); } }
Follow up 2:
Find all possible combinations of k numbers that add up to a number n, given that only numbers from 1 to 9 can be used and each combination should be a unique set of numbers.
public List<List<Integer>> combinationSum3(int k, int n) { List<List<Integer>> rst = new ArrayList<>(); if(k == 0){ return rst; } List<Integer> list = new ArrayList<>(); helper(rst, list, n, k, 1); return rst; } private void helper(List<List<Integer>> rst, List<Integer> list, int target, int size, int pos){ if(target == 0 && list.size() == size){ rst.add(new ArrayList<>(list)); return; } for(int i = pos; i <= 9; i++){ list.add(i); helper(rst, list, target - i, size, i + 1); list.remove(list.size() - 1); } }
Follow up 3:
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.
首先最直接的想法是backtracking:
但是backtracking会超时。public int combinationSum4(int[] nums, int target) { if(nums == null || nums.length == 0){ return 0; } List<List<Integer>> rst = new ArrayList<>(); Arrays.sort(nums); helper(rst, new ArrayList<Integer>(), nums, target); return rst.size(); } private void helper(List<List<Integer>> rst, List<Integer> list, int[] nums, int target){ if(target == 0){ rst.add(new ArrayList<>(list)); return; } for(int i = 0; i <= nums.length - 1; i++){ if(target < nums[i]){ return; } list.add(nums[i]); helper(rst, list, nums, target - nums[i]); list.remove(list.size() - 1); } }
这里可以用dp来解决:
public int combinationSum4(int[] nums, int target) { Arrays.sort(nums); int[] dp = new int[target + 1]; for(int i = 0; i <= target; i++){ for(int num : nums){ if(num > i){ break; } if(num == i){ dp[i] += 1; } if(num < i){ dp[i] += dp[i - num]; } } } return dp[target]; }

Comments
Post a Comment