二叉树基础
关于二叉树的问题,请参考二叉树的预备知识,以及剑指offer之前的两道二叉树的题目。
《剑指offer》预备知识-链表与二叉树
《剑指offer》06&07、二叉树的重构与下一个结点
树的子结构
offer23的问题是给出两棵树A和B,判断B是否A的子结构(我们约定空树不是任何一棵树的子结构)
涉及到树的结构问题,80%以上是递归。我们需要先把找子结构的思路写出来,然后再顺势写出递归。
1、首先要判断AB是否空树
2、然后要找到A的一个节点,使得它恰为B的根节点;这个节点就是递归的起点,我们暂时称之为起始节点。
关于寻找这个节点,这里存在第一个递归,如果A的根节点不是B的根节点,那就递归遍历A的左右子树去寻找这个起始节点。
3、找到起始节点以后,用第二个递归遍历判断A的这棵子树是否和B完全一致:如果节点不同就返回上一层,重新寻找新的起始节点;如果节点相同,递归遍历A的左右子树继续判断。
这样一来题解就很明显了,通过两次递归,分别完成寻找起始节点和判断树的结构是否相同两个工作。代码如下:
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
# offer23-solution
class Solution:
def HasSubtree(self, pRoot1, pRoot2):
result = False
if pRoot1 and pRoot2:
if pRoot1.val == pRoot2.val:
result = self.SubtreeCore(pRoot1, pRoot2) # 根节点相同,进入第二个递归
if not result:
result = self.HasSubtree(pRoot1.left, pRoot2) # 左子树递归找相同的节点
if not result:
result = self.HasSubtree(pRoot1.right, pRoot2) # 右子树递归找相同的节点
return result
def SubtreeCore(self, pRoot1, pRoot2):
if pRoot1 == None or pRoot2 == None: # A树或B树为空树
return True
elif pRoot1.val != pRoot2.val: # 节点不同,不是子结构
return False
else: # 对左右子树进行递归
return self.SubtreeCore(pRoot1.left, pRoot2.left)
and self.SubtreeCore(pRoot1.right, pRoot2.right)
镜像二叉树
镜像二叉树实际就是要交换它的左右子树。那就用一次递归就好了……代码1给出的是原地修改生成镜像树,代码2给出的是生成一棵新的镜像二叉树,参考给出的是非递归的方法。
# offer24-solution1
# 其实not root.left and not root.right可以写得更为简洁,请各位自行思考,我在这里写冗余了
def Mirror1(self, root):
if not root or not root.left and not root.right:
return root
root.left, root.right = root.right, root.left
if root.left:
self.Mirror1(root.left)
if root.right:
self.Mirror1(root.right)
# offer24-solution2
def Mirror2(self, root):
if not root or not root.left and not root.right:
return
newTree = treeNode(root.val)
if root.left:
newTree.right = self.Mirror2(root.left)
if root.right:
newTree.left = self.Mirror2(root.right)
return newTree
非递归的方式,就要借助栈和队列了。
二叉树的镜像递归非递归求解