算法通关村——透析回溯的模板

回溯的基本思想是从一个初始状态开始,按照一定的规则向前探索,寻找问题的解。

如果发现状态不对或者无法达到目标就会退回到上一个状态,重新选择另一种可能。

回溯的模板如下:

void backtracking(参数) {
        if (终止条件) {
            存放结果;
            return;
        }
        for (选择本层集合中元素(画成树,就是树节点孩子的大小)){
            处理节点;
            backtracking();
            回溯,撤销处理结果;
        }
    }

这代码和N叉树的遍历过程是极其相似的

public static void treeDFS(TreeNode root) {
    //递归必须要有终止条件
    if (root == null){
     return;
    }
 // 处理节点
    System.out.println(root.val);
 
    //通过循环,分别遍历N个子树
    for (int i = 1; i <= nodes.length; i++) {
        treeDFS("第i个子节点");
    }
}

但是还是有所区别,回溯的模板比N叉树的遍历过程多了一个手动撤回的操作,正好对应了回溯里如果发现状态不对就退回到上一个状态的思想。

最后就放一个经典题目,来看看回溯思想落在实战中长什么样

LeetCode77 :给定两个整数 n 和 k,返回 1 ... n 中所有可能的 k 个数的组合。

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

public List<List<Integer>> combine(int n, int k) {
        List<List<Integer>> resultList = new ArrayList<>();
        if (k <= 0 || n < k) {
            return resultList;
        }
//        用户返回结果
        Deque<Integer> path = new ArrayDeque<>();
        dfs(n, k, 1, path, res);
        return res;
    }
 
    public void dfs(int n, int k, int startIndex, Deque<Integer> path, List<List<Integer>> resultList) {
        // 递归终止条件是:path 的长度等于 k
        if (path.size() == k) {
            resultList.add(new ArrayList<>(path));
            return;
        }
 
        // 针对一个结点,遍历可能的搜索起点,其实就是枚举
     for (int i = startIndex; i <= n; i++) {
            // 向路径变量里添加一个数,就是上图中的一个树枝的值
           path.addLast(i);
            // 搜索起点要加1是为了缩小范围,下一轮递归做准备,因为不允许出现重复的元素
           dfs(n, k, i + 1, path, resultList);
            // 递归之后需要做相同操作的逆向操作,具体后面继续解释
           path.removeLast();
        }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值