zoukankan      html  css  js  c++  java
  • 回溯算法

    回溯法有“通用解题法”之称。用它可以系统地搜索问题的所有解。

    回溯法是一个既带有系统性又带有跳跃性的搜索算法。它在问题的解空间树中,按深度优先策略,从根结点出发搜索解空间树。算法搜索至解空间树的任一结点时,先判断该结点是否包含问题的解。如果肯定不包含,则跳过对以该结点为根的子树的搜索,逐层向其祖先结点回溯;否则,进入该子树,继续按深度优先策略搜索。

    回溯法求问题的所有解时,要回溯到根,且根结点的所有子树都被搜索遍才结束。回溯法求问题的一个解时,只要搜索到问题的一个解就可结束。

    这种以深度优先方式系统搜索问题解的算法称为回溯法,它适用于求解组合数较大的问题。也经常适用于求解二叉树的相关问题,例如以下两个二叉树路径总和的问题:

    二叉树是否存在某一路径总和

    示例:
    给定如下二叉树,以及目标和 sum = 22

                                  5			
                                 / 
                                4   8		(左)sum = sum - 5 = 17
                               /   / 
                              11  13  4		(左)sum	= sum - 4 = 13
                             /        
                            7    2      1	        (左)sum = sum - 11 = 2 
    

    返回 true, 因为存在目标和为 22 的根节点到叶子节点的路径 5->4->11->2

    使用递归,分别遍历左右子树,当左右子树中有一个路径满足条件,则返回true

    递归结束条件:root.left == null && root.right == null && sum == root.val

    sum的值自顶向下 逐层递减 sum = sum - root.val。

    class Solution {
        public boolean hasPathSum(TreeNode root, int sum) {
           
            // 当前节点为空,sum 大于等于 0;例如:root = [],sum = 0、sum = 1
            if (root == null && sum >= 0) {
                return false;
            }
    
            // 当前节点为空,sum 小于 0;例如:root = [],sum = -1
            if (root == null && sum < 0) {
                return false;
            }
    
            // 当且仅当 左右孩子节点为空 且 sum = root.val 时,则找到目标
            if (root.left == null && root.right == null && sum == root.val) {
                return true;
            }
    
            // 遍历目标节点的左子树和右子树 ,当左右子树中有一个返回true(即找到目标) 时,则返回true;
            // sum = sum - root.val,当到达叶子节点且sum= root.val则 找到目标
            return hasPathSum(root.left, sum - root.val) || hasPathSum(root.right, sum - root.val);
        }
    }
    

    二叉树路径总和为某值的所有路径

    输入一棵二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径。从树的根节点开始往下一直到叶节点所经过的节点形成一条路径。

    示例:
    给定如下二叉树,以及目标和 sum = 22

                  5
                 / 
                4   8
               /   / 
              11  13  4
             /      / 
            7    2  5   1
    

    返回:

    [
       [5,4,11,2],
       [5,8,4,5]
    ]
    

    提示:

    1. 节点总数 <= 10000

    解题思路:从根节点开始递归遍历,每遍历一个节点,则把当前节点入栈。

    同时判断 sum == 当前节点.val(每遍历一个节点时,其sum = sum - 父节点.val)。

    如果到达叶子节点且sum = 当前节点.val,则说明找到了正确的路径,就将栈内的所有元素保存到链表中。

    每次返回父节点前都要将栈顶的节点删除再返回父节点。

    class Solution {
        List<List<Integer>> resList = new ArrayList<>();
        LinkedList<TreeNode> stack = new LinkedList<>();
    
        public List<List<Integer>> pathSum(TreeNode root, int sum) {
            if (root == null) {
                return new ArrayList<>();
            }
    
            findPath(root, sum);
    
            return resList;
        }
    
        public void findPath(TreeNode root, int currentSum) {
    
            // 将当前根节点入栈
            stack.push(root);
    
            // 判断节点状态及sum数值,找到合适的路径就将栈内元素保存到链表中
            if ((root.left == null && root.right == null) && currentSum == root.val) {
    
                ArrayList<Integer> list = new ArrayList<>();
    
                for (int i = stack.size() - 1; i >= 0; i--) {
                    TreeNode node = stack.get(i);
                    list.add(node.val);
                }
                resList.add(list);
            }
    
            // 如果不是叶子节点,则继续遍历其子节点
            if (root.left != null) {
                findPath(root.left, currentSum - root.val);
            }
    
            if (root.right != null) {
                findPath(root.right, currentSum - root.val);
            }
    
            // 递归返回其父节点前,将栈内路径上的当前节点删除
            stack.pop();
        }
    }
    
  • 相关阅读:
    C# 图形普通处理,resize ,水印..
    图像处理 形态学 (腐蚀 膨胀 开闭运算 连通分量....)
    获取usb设备父系或子代
    aforge通过角点匹配图片相似度
    CentOS 手动增加、删除swap区
    Zabbix 中文使用手册
    CentOS7下Firewall防火墙配置用法详解
    CentOS7安装Zabbix
    宅男也可变形男-我是如何在11个月零27天减掉80斤的
    CentOS环境下使用GIT基于Nginx的私服搭建全过程
  • 原文地址:https://www.cnblogs.com/code-duck/p/13597195.html
Copyright © 2011-2022 走看看