【LeetCode】77. 组合+39. 组合总和+40. 组合总和 II

题目链接:77. 组合
题目描述:给定两个整数 n 和 k,返回 1 … n 中所有可能的 k 个数的组合。
样例:

输入: n = 4, k = 2
输出:
[
  [2,4],
  [3,4],
  [2,3],
  [1,2],
  [1,3],
  [1,4],
]

思路:常规解法,递归+回溯,用一个下标startIndex表示当前搜索的起点,边搜便记录当前这条路径上的值,当搜到一轮答案之后回溯,删掉最后一个值,换条路径继续搜。
代码:

class Solution {
    
    
    public void dfs(int n,int startIndex,List<Integer> list,List<List<Integer>> ans,int k){
    
    
        if(k==list.size()){
    
    
            List<Integer> list1=new ArrayList<>(list);
            ans.add(list1);
            return ;
        }
        for(int i=startIndex;i<=n;i++){
    
    
            list.add(i);
            dfs(n,i+1,list,ans,k);
            list.remove(list.size()-1);
        }
    }
    public List<List<Integer>> combine(int n, int k) {
    
    
        List<List<Integer>> ans=new ArrayList<List<Integer>>();
        if(n<k||k<=0){
    
    
            return ans;
        }
        List<Integer> list=new ArrayList<>();
        dfs(n,1,list,ans,k);
        return ans;
    }
}

相似题目:46. 全排列+47. 全排列 II
进一步,看39. 组合总和
题目描述:给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

candidates 中的数字可以无限制重复被选取。
样例:

输入:candidates = [2,3,6,7], target = 7,
所求解集为:
[
  [7],
  [2,2,3]
]
输入:candidates = [2,3,5], target = 8,
所求解集为:
[
  [2,2,2,2],
  [2,3,3],
  [3,5]
]

数据范围:

1 <= candidates.length <= 30
1 <= candidates[i] <= 200
candidate 中的每个元素都是独一无二的。
1 <= target <= 500

思路:和上面思路差不多,只是这里每个元素可以重复利用,因此搜索时候还是从当前节点开始搜。
代码:

class Solution {
    
    
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
    
    
        List<Integer> list=new ArrayList<>();
        List<List<Integer>> ans=new ArrayList<List<Integer>>();
        dfs(candidates,0,list,ans,target);
        return ans;
    }
    public void dfs(int nums[],int startIndex,List<Integer> list,List<List<Integer>> ans,int target){
    
    
        if(target<0) return;
        if(target==0){
    
    
            ans.add(new ArrayList<>(list));
            return ;
        }
        for(int i=startIndex;i<nums.length;i++){
    
    
            list.add(nums[i]);
            dfs(nums,i,list,ans,target-nums[i]);//可以重复利用每个元素,因此还是从当前位置开始搜
            list.remove(list.size()-1);
        }
    }

}

题目链接:40. 组合总和 II
题目描述:给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

candidates 中的每个数字在每个组合中只能使用一次。

  • 所有数字(包括目标数)都是正整数。
  • 解集不能包含重复的组合。

样例:

输入: candidates = [10,1,2,7,6,1,5], target = 8,
所求解集为:
[
  [1, 7],
  [1, 2, 5],
  [2, 6],
  [1, 1, 6]
]
输入: candidates = [2,5,2,1,2], target = 5,
所求解集为:
[
  [1,2,2],
  [5]
]

思路:一个数字只能用一次,做法就是先排个序,然后相邻两个相同的就直接continue以免重复记录答案。

class Solution {
    
    
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
    
    
        Arrays.sort(candidates);
        List<Integer> list=new ArrayList<>();
        List<List<Integer>> ans=new ArrayList<List<Integer>>();
        dfs(candidates,target,list,ans,0);
        return ans;
    }
    public void dfs(int []nums,int target,List<Integer> list,List<List<Integer>> ans,int startIndex){
    
    
        if(target<0) return;
        if(target==0){
    
    
            List<Integer> list1=new ArrayList<>(list);
            ans.add(list1);
            return;
        }
        for(int i=startIndex;i<nums.length;i++){
    
    
            if(i>startIndex&&nums[i] == nums[i-1]) continue;//避免出现重复情况
            list.add(nums[i]);
            dfs(nums,target-nums[i],list,ans,i+1);
            list.remove(list.size()-1);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/dl962454/article/details/115023866