77 从1~n 中产生K个组合, 因为1~n 没有重复元素,所以很简单

class Solution {
    public List<List<Integer>> combine(int n, int k) {
        
        int[] nums= new int[n];
        for(int i=1; i<=n; i++){
            nums[i-1] = i;
        }

        List<List<Integer>> result = new ArrayList<>(); 
        dfs(new ArrayList<>(), 0, nums,k,result);
        return result;
    }
        
   private void dfs(List<Integer> curResult, int start, int[] nums, int k, List<List<Integer>> result){
            if(curResult.size() == k){
                result.add(new ArrayList<>(curResult));
                return;
            }
        
           for(int i=start; i<nums.length; i++){
               curResult.add(nums[i]);
               dfs(curResult,i+1,nums,k,result);
               curResult.remove(curResult.size()-1);
           }
    }    
}

 

 

39. 

 前提: 1. 所有数都是positive的 2. 所有数没有duplicated的

并且一个数可以重复选择

Input: candidates = [2,3,6,7], target = 7,
A solution set is:
[
  [7],
  [2,2,3]
]

算法: 就是简单的组合问题,唯一需要注意的是, 从左往右看, 对于2, 选了3 后 变成 [2 3] ,那么对于3 就不能再选2了。 换句话说, 每次只能添加 index >= current_index的, 如果不允许重复添加,那条件就是index > current_index才行。
算法的递归树如下所示:

class Solution {
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        
        List<List<Integer>> result = new ArrayList<>();
        dfs(0, new ArrayList<Integer>(), result,0,target,candidates);
        return result;
    }
    
    private void dfs(int start, List<Integer> curResult, List<List<Integer>> result,int sum, int target,int[] nums){
        if(sum> target) return;  
        if(sum== target) {
            result.add(new ArrayList<>(curResult));
            return;
        }  
        for(int i=start; i<nums.length; i++){
            curResult.add(nums[i]);
            sum+=nums[i];
            dfs(i, curResult,result,sum,target,nums);
            curResult.remove(curResult.size()-1);
            sum-=nums[i];
        }
    }
}

 

 

40.  

 1. 条件变成了  数字有重复 , 有重复的处理方法都是先排序。

2. 并且返回结果仍然需要unique 的组合

 3. 每个数字只能被放一次,   和39不同稍微改一下 递归时条件 从index = cur_index+1 放 就不会重复了

Input: candidates = [10,1,2,7,6,1,5], target = 8,
A solution set is:
[
  [1, 7],
  [1, 2, 5],
  [2, 6],
  [1, 1, 6]
]

画出的递归树如下:

 


class Solution {
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        
        List<List<Integer>> result = new ArrayList<>();
        Arrays.sort(candidates);
        dfs(0, new ArrayList<Integer>(), result,0,target,candidates);
        return result;
    }
    
    private void dfs(int start, List<Integer> curResult, List<List<Integer>> result,int sum, int target,int[] nums){
        if(sum >= target){
            if(sum>target) return;
            else {
                result.add(new ArrayList<>(curResult));
                return;
            }
        }
        
        for(int i=start; i<nums.length; i++){
            if(i > start && nums[i] == nums[i-1]) continue; 
           
            curResult.add(nums[i]);
            sum+=nums[i];
            dfs(i+1, curResult,result,sum,target,nums);// 每个数字只能被放一次, 因此得从 i+1开始
            curResult.remove(curResult.size()-1);
            sum-=nums[i];
        }
    }
}

 216

从1-9里选k 个数, 组成的和为n。 和39基本一样,只是 dfs 返回的条件略有不同而已。

Input: k = 3, n = 7
Output: [[1,2,4]]

class Solution {
    public List<List<Integer>> combinationSum3(int k, int n) {
        
        int[] nums = {1,2,3,4,5,6,7,8,9};
        List<List<Integer>> result = new ArrayList<>();
        
        dfs(0,k,n,nums,new ArrayList<>(), 0, result);
        return result;
    }
    
    private void dfs(int start, int k, int n, int[] nums, List<Integer> curResult, int sum, List<List<Integer>> result){
        if(sum > n || curResult.size() >k) return;
        
        if(sum == n && curResult.size() == k){
            result.add(new ArrayList<>(curResult));
            return;
        }
        
        for(int i= start; i<nums.length; i++){
            sum += nums[i];
            curResult.add(nums[i]);
            dfs(i+1,k,n, nums,curResult,sum,result);
            curResult.remove(curResult.size()-1);
            sum -= nums[i];
        }
    }
}

 

posted on 2018-11-10 03:50  KeepAC  阅读(125)  评论(0编辑  收藏  举报