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

2023-08-31 13:52:58 浏览数 (1)

剑指 Offer 26. 树的子结构

题目

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

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

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

例如: 给定的树 A:

代码语言:javascript复制
     3  
    / 
   4   5  
  /   
 1   2

给定的树 B:

代码语言:javascript复制
   4 
  /
 1

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

示例 1:

代码语言:javascript复制
输入: A = [1,2,3], B = [3,1]
输出: false

示例 2:

代码语言:javascript复制
输入: A = [3,4,5,1,2], B = [4,1]
输出: true

限制:

0 <= 节点个数 <= 10000

方法一:先序遍历

思路

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

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

recur(A, B) 函数:

1. 终止条件:

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

2. 返回值:

代码语言:javascript复制
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:

代码语言:javascript复制
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:

代码语言:javascript复制
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

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

例如输入:

代码语言:javascript复制
     4  
   /     
  2     7  
 /    /   
1   3 6   9

镜像输出:

代码语言:javascript复制
     4
   /   
  7     2
 /    / 
9   6 3   1

示例 1:

代码语言:javascript复制
输入: root = [4,2,7,1,3,6,9]
输出: [4,7,2,9,6,3,1]

限制:

0 <= 节点个数 <= 1000

方法一:递归

思路

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

解题

Python:

代码语言:javascript复制
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:

代码语言:javascript复制
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;
    }
}
 

0 人点赞