【算法题解】 Day23 搜索与回溯

简介: 今天的算法是 「搜索与回溯」 相关,“算法题解系列文章旨在精选重点与易错的算法题,总结常见的算法思路与可能出现的错误,以实战习题的形式理解算法,使用算法。”

剑指 Offer 26. 树的子结构

题目

剑指 Offer 26. 树的子结构 难度:medium

输入两棵二叉树A和B,判断B是不是A的子结构。(约定空树不是任意一个树的子结构)

B是A的子结构, 即 A中有出现和B相同的结构和节点值。

例如:
给定的树 A:

     3  
    / \
   4   5  
  / \  
 1   2

给定的树 B:

   4 
  /
 1

返回 true,因为 B 与 A 的一个子树拥有相同的结构和节点值。

示例 1:

输入: A = [1,2,3], B = [3,1]
输出: false

示例 2:

输入: A = [3,4,5,1,2], B = [4,1]
输出: true

限制:

0 <= 节点个数 <= 10000
 

方法一:先序遍历

思路

若树 B 是树 A 的子结构,则子结构的根节点可能为树 A 的任意一个节点。因此,判断树 B 是否是树 A 的子结构,需完成以下两步工作:

  1. 先序遍历树 A 中的每个节点 $n_A$;(对应函数 isSubStructure(A, B)
  2. 判断树 A 中 以 $n_A$ 为根节点的子树 是否包含树 B 。(对应函数 recur(A, B)

recur(A, B) 函数:

1. 终止条件:

1. 当节点 B 为空:说明树 B 已匹配完成(越过叶子节点),因此返回 true ;
2. 当节点 A 为空:说明已经越过树 A 叶子节点,即匹配失败,返回 false ;
3. 当节点 A 和 B 的值不同:说明匹配失败,返回 false ;

2. 返回值:

1. 判断 A 和 B 的左子节点是否相等,即 recur(A.left, B.left) ;
2. 判断 A 和 B 的右子节点是否相等,即 recur(A.right, B.right) ;

isSubStructure(A, B) 函数:

  1. 特例处理: 当 树 A 为空  树 B 为空 时,直接返回 false ;
  2. 返回值:  若树 B 是树 A 的子结构,则必满足以下三种情况之一,因此用或 || 连接:

    1. 以 节点 A 为根节点的子树 包含树 B ,对应 recur(A, B)
    2. 树 B 是 树 A 左子树 的子结构,对应 isSubStructure(A.left, B)
    3. 树 B 是 树 A 右子树 的子结构,对应 isSubStructure(A.right, B)

 

解题

Python:

class Solution:
    def isSubStructure(self, A: TreeNode, B: TreeNode) -> bool:
        def recur(A, B):
            if not B: return True
            if not A or A.val != B.val: return False
            return recur(A.left, B.left) and recur(A.right, B.right)

        return bool(A and B) and (recur(A, B) or self.isSubStructure(A.left, B) or self.isSubStructure(A.right, B))

Java:

class Solution {
    public boolean isSubStructure(TreeNode A, TreeNode B) {
        return (A != null && B != null) && (recur(A, B) || isSubStructure(A.left, B) || isSubStructure(A.right, B));
    }
    boolean recur(TreeNode A, TreeNode B) {
        if(B == null) return true;
        if(A == null || A.val != B.val) return false;
        return recur(A.left, B.left) && recur(A.right, B.right);
    }
}

 

剑指 Offer 27. 二叉树的镜像

题目

剑指 Offer 27. 二叉树的镜像 难度:easy

请完成一个函数,输入一个二叉树,该函数输出它的镜像。

例如输入:

     4  
   /   \  
  2     7  
 / \   / \  
1   3 6   9

镜像输出:

     4
   /   \
  7     2
 / \   / \
9   6 3   1

示例 1:

输入: root = [4,2,7,1,3,6,9]
输出: [4,7,2,9,6,3,1]

限制:

0 <= 节点个数 <= 1000
 

方法一:递归

思路

这是一道很经典的二叉树问题。显然,我们从根节点开始,递归地对树进行遍历,并从叶子节点先开始翻转得到镜像。如果当前遍历到的节点 $\textit{root}$ 的左右两棵子树都已经翻转得到镜像,那么我们只需要交换两棵子树的位置,即可得到以 $\textit{root}$ 为根节点的整棵子树的镜像。
 

解题

Python:

class Solution:
    def mirrorTree(self, root: TreeNode) -> TreeNode:
        if not root:
            return root
        
        left = self.mirrorTree(root.left)
        right = self.mirrorTree(root.right)
        root.left, root.right = right, left
        return root

Java:

class Solution {
    public TreeNode mirrorTree(TreeNode root) {
        if (root == null) {
            return null;
        }
        TreeNode left = mirrorTree(root.left);
        TreeNode right = mirrorTree(root.right);
        root.left = right;
        root.right = left;
        return root;
    }
}

 

后记

📝 上篇精讲: 【算法题解】 Day22 搜索与回溯
💖 我是  𝓼𝓲𝓭𝓲𝓸𝓽,期待你的关注;
👍 创作不易,请多多支持;
🔥 系列专栏: 算法题解
目录
相关文章
|
1月前
|
算法 程序员 数据处理
算法与人生 揭秘C语言中高效搜索的秘诀——二分查找算法详解
算法与人生 揭秘C语言中高效搜索的秘诀——二分查找算法详解
|
3月前
|
算法
【算法系列篇】递归、搜索和回溯(四)
【算法系列篇】递归、搜索和回溯(四)
|
1月前
|
算法
回溯算法练习题
回溯算法练习题
11 0
|
1月前
|
算法 Java 定位技术
【数据结构与算法】递归、回溯、八皇后 一文打尽!
【数据结构与算法】递归、回溯、八皇后 一文打尽!
|
2月前
|
算法 测试技术 C++
【记忆化搜索】【剪枝】【C++算法】1553吃掉 N 个橘子的最少天数
【记忆化搜索】【剪枝】【C++算法】1553吃掉 N 个橘子的最少天数
|
2月前
|
算法 测试技术 C++
【动态规划】【记忆化搜索】【C++算法】664. 奇怪的打印机
【动态规划】【记忆化搜索】【C++算法】664. 奇怪的打印机
|
2月前
|
移动开发 算法 测试技术
【动态规划】【记忆化搜索】C++算法:546移除盒子
【动态规划】【记忆化搜索】C++算法:546移除盒子
|
3月前
|
算法
【算法系列篇】递归、搜索和回溯(三)
【算法系列篇】递归、搜索和回溯(三)
|
3月前
|
算法
【算法系列篇】递归、搜索和回溯(二)
【算法系列篇】递归、搜索和回溯(二)
|
3月前
|
算法
【算法系列篇】递归、搜索与回溯(一)
【算法系列篇】递归、搜索与回溯(一)