回溯力扣77,39

今天将两道相似的题写下来,这两道题都用到了回溯的方法。
77 组合、
给定两个整数 n 和 k,返回 1 ... n 中所有可能的 k 个数的组合。
示例:

输入: n = 4, k = 2

输出:

[
  [2,4],
  [3,4],
  [2,3],
  [1,2],
  [1,3],
  [1,4],
]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/combinations
思路是看的iweiwei1419大神的。讲的比较透彻,在力扣的题解页面代码的剪枝方面讲解的同样透彻。
代码为:

    public List> combine(int n, int k) {
        List> res = new ArrayList<>();
        if(n <= 0 || n < k)
            return res;
        Deque path = new ArrayDeque<>();
        dfs(n,k,1,res,path);
        return res;
    }
    public void dfs(int n, int k, int begin, List> res, Deque path){
        if(path.size() == k){
            res.add(new ArrayList<>(path));
            return;
        }
        /*
        搜索起点的上界 + 接下来要选择的元素个数 - 1 = n;
        其中,接下来要选择的元素个数 = k - path.size(),整理得到:
        搜索起点的上界 = n - (k - path.size()) + 1
        */
        //for(int i = begin ; i <= n ; i++){
        for(int i = begin ; i <= n-(k-path.size())+1 ; i++){
            path.addLast(i);
            dfs(n,k,i+1,res,path);
            path.removeLast();
        }
    }
}

在看类似的39题,也是同样用的是回溯的思路,在剪枝方面还是借助了大佬的思路。
给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的数字可以无限制重复被选取。
说明:

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

示例 1:

输入:candidates = [2,3,6,7], target = 7,

所求解集为:

[
  [7],
  [2,2,3]
]

示例 2:

输入:candidates = [2,3,5], target = 8,

所求解集为:

[
  [2,2,2,2],
  [2,3,3],
  [3,5]
]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/combination-sum

 /**
     * 39. 组合总和
     * 与上面的一样利用回溯的解法
     * @param args
     */
    public List> combinationSum(int[] candidates, int target) {
        List> res = new ArrayList<>();
        Deque path = new ArrayDeque<>();
        if(candidates.length < 0)
            return res;
        Arrays.sort(candidates);  //剪枝,排序加强一些
        backtrack(candidates,target,0,path,res);
        return res;
    }
    public  void backtrack(int[] candidates, int target, int begin, Deque path, List> res){
        if(target < 0)                            //终止条件
            return;
        if(target == 0){                          //终止条件
            res.add(new ArrayList<>(path));             //存放结果
            return;
        }
        for(int i = begin ; i < candidates.length ; i++){                     //需要开始进行的点  ,,,,
            //当target - candidates[i] < 0 就表示现在数之和已经大于目标值,就不用再往下进行了
            if (target - candidates[i] < 0){
                break;
            }
            path.addLast(candidates[i]);  //回溯开始之前将数字加进去    //递归,处理节点;           
            backtrack(candidates,target-candidates[i],i,path,res);  //进入回溯注意还要从i开始。判断是不是全是i还是有几个i
            path.removeLast();  //回溯之后要回到原状态             //  回溯,撤销处理结果
        }
    }

你可能感兴趣的:(回溯力扣77,39)