回溯法

http://www.imooc.com/article/39641
重新梳理一遍:
  如果一个题目给你几个数组,要求得到他们的组合、子集、或是排列,那么这时候可以考虑使用回溯法。

回溯法套路:

  • 一个返回结果变量res,一个临时变量或者叫路径变量temp
  • 对于不要求重复的可能需要排序,需要i > 0 && nums[i] == nums[i - 1]这样的操作剪枝
  • 往全局变量中添加临时变量时,如果临时变量是引用类型,要注意建立一个新的对象,不然后续值可能会改变。res.add(new ArrayList<>(temp));
例子

40数组总和2

给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的每个数字在每个组合中只能使用一次
说明:
所有数字(包括目标数)都是正整数
解集不能包含重复的组合
示例 1:
输入: candidates = [10,1,2,7,6,1,5], target = 8,
所求解集为:
[
[1, 7],
[1, 2, 5],
[2, 6],
[1, 1, 6]
]

    public static List<List<Integer>> combinationSum2(int[] candidates, int target) {
        List<List<Integer>> res = new ArrayList<>();
        if (candidates == null) {
            return res;
        }
        List<Integer> temp = new ArrayList<>();
        Arrays.sort(candidates);
        traceBack(res, temp, candidates, target, 0, 0);

        return res;
    }
    //98,94
    public static void traceBack2(List<List<Integer>> res, List<Integer> temp, int[] candidates, int target, int sum, int start) {

        if (sum == target) {
            res.add(new ArrayList<>(temp));
            return;
        }
        //int i=start ,表示只能使用一次。
        for (int i = start; i < candidates.length; i++) {
            //改进了一下,提前退出,不进入递归
            if (candidates[i] + sum > target) {
                return;
            }
            //这是针对同一层不能选择重复的
            if (i > start && candidates[i] == candidates[i - 1]) {
                continue;
            }
            temp.add(candidates[i]);
            traceBack2(res, temp, candidates, target, sum + candidates[i], i + 1);
            temp.remove(temp.size() - 1);
        }
    }
套路解释

39. 组合总和
40. 数组总和2
46. 全排列
47. 全排列2
77. 组合
78. 子集
90. 子集 II
784. 字母大小写全排列
51. N皇后

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。