二叉树复习
各种遍历后结果
pre:12453687
mid:42516837
last:45286731
class TreeNode:
def __init__(self, val):
self.val = val
self.left = None
self.right = None
def pre_recursion_order(root):
"""递归方式 执行遍历"""
if root == None:
return None
print(root.val) # 先序遍历
pre_recursion_order(root.left)
# print(root.val) # 中序遍历
pre_recursion_order(root.right)
# print(root.val) # 先序遍历
def pre_iteration_order(root):
"""迭代方式 执行遍历"""
if root == None:
return None
tempNode = root
stack = []
while stack or tempNode:
while tempNode:
# print(tempNode.val) # 先序打印
stack.append(tempNode)
tempNode = tempNode.left
node = stack.pop()
print(node.val) # 中序遍历
tempNode = node.right
def last_iteration_order(root):
"""后续稍微麻烦,左,右,根"""
if root == None:
return None
tempNode = root
stack = []
while stack or tempNode:
while tempNode:
stack.append(tempNode)
tempNode = tempNode.left
node = stack[-1] # 第一次这里node=4, stack=[1, 2, 4]
tempNode = node.right
if node.right == None:
node = stack.pop()
print(node.val) #
while stack and node == stack[-1].right: #
node = stack.pop()
print(node.val) #
if __name__ == "__main__":
t1 = TreeNode(1)
t2 = TreeNode(2)
t3 = TreeNode(3)
t4 = TreeNode(4)
t5 = TreeNode(5)
t6 = TreeNode(6)
t7 = TreeNode(7)
t8 = TreeNode(8)
t1.left = t2
t1.right = t3
t2.left = t4
t2.right = t5
t3.left = t6
t3.right = t7
t6.right = t8
pre_recursion_order(t1)
print('---' * 10)
pre_iteration_order(t1)
print('---' * 10)
last_iteration_order(t1)
重建二叉树
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
# 返回构造的TreeNode根节点
def reConstructBinaryTree(self, pre, tin):
# write code here
if pre == []:
return None
root = TreeNode(pre[0])
pos = tin.index(pre[0])
root.left = self.reConstructBinaryTree(pre[1:pos+1], tin[:pos])
root.right = self.reConstructBinaryTree(pre[pos+1:], tin[pos+1:])
return root
树的子结构:
输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def HasSubtree(self, pRoot1, pRoot2):
# write code here
if pRoot1 == None or pRoot2 == None:
return False
return self.judge_sub_tree(pRoot1, pRoot2)
def judge_sub_tree(self, root1, root2):
if root2 == None:
return True
if root1 == None:
return root1 == root2
res = False
if root1.val == root2.val: # 看这个子结构是不是在左节点侧,或者在右节点侧
res = self.judge_sub_tree(root1.left, root2.left) and self.judge_sub_tree(root1.right, root2.right)
return res or self.judge_sub_tree(root1.left, root2) or self.judge_sub_tree(root1.right, root2)
二叉树的镜像:
操作给定的二叉树,将其变换为源二叉树的镜像
二叉树的镜像定义:源二叉树
8
/ \
6 10
/ \ / \
5 7 9 11
镜像二叉树
8
/ \
10 6
/ \ / \
11 9 7 5
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
# 返回镜像树的根节点
def Mirror(self, root):
# write code here
if root == None:
return None
root.left, root.right = root.right, root.left
self.Mirror(root.left)
self.Mirror(root.right)
return root
从上往下打印二叉树 (别和前序、中序、后续、遍历搞混了!)
# 从上往下打印出二叉树的每个节点,同层节点从左至右打印
class Solution:
# 返回从上到下每个节点值列表,例:[1,2,3]
def PrintFromTopToBottom(self, root):
# write code here
if root == None:
return []
res = []
temp = [root]
while temp:
node = temp.pop(0)
res.append(node.val)
if node.left:
temp.append(node.left)
if node.right:
temp.append(node.right)
return res
二叉搜索树的后续遍历序列
题目描述
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。
二叉搜索树复习:
# 这题的验证程序确实傻逼,即使收入为[]它也是一个搜索二叉树啊
class Solution:
def VerifySquenceOfBST(self, sequence):
# write code here
# 主要思路是:后续遍历,左右根,最后一个是根节点
# 那么前面的 [1, 4, 2, 6, 11, 9, 5], 那么这里5是根节点
# 那么 143 为左子树, 6 11 9 为右子树,
# 那么 如果遍历过程中,找到第一个数的index,它大于根节点,那么就分出了左右子树
# 如果 6 后面还出现了小于于5的树,那就判定为false 比如 [1, 4, 2, 6, 2, 9, 5]
if sequence == []:
return False
root = sequence[-1]
sequence.pop()
index = None
for i in range(len(sequence)):
if not index and sequence[i] > root:
index = i # 比如找到 6 的位置,index = 3
if index != None and sequence[i] < root: # 继续往下遍历,看有没有其他数小于5
return False
if sequence[:index] == []:
return True
else:
left_res = self.VerifySquenceOfBST(sequence[:index])
if sequence[index:] == []:
return True
else:
right_res = self.VerifySquenceOfBST(sequence[index:])
return left_res and right_res
二叉树中和为某一路径的值
输入一颗二叉树的根节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。(注意: 在返回值的list中,数组长度大的数组靠前)
# 复习 浅拷贝 & 深拷贝
>>> import copy
>>> origin = [1, 2, [3, 4]]
#origin 里边有三个元素:1, 2,[3, 4]
>>> cop1 = copy.copy(origin)
>>> cop2 = copy.deepcopy(origin)
>>> cop1 == cop2
True
>>> cop1 is cop2
False
#cop1 和 cop2 看上去相同,但已不再是同一个object
>>> origin[2][0] = "hey!"
>>> origin
[1, 2, ['hey!', 4]]
>>> cop1
[1, 2, ['hey!', 4]]
>>> cop2
[1, 2, [3, 4]]
#把origin内的子list [3, 4] 改掉了一个元素,观察 cop1 和 cop2
举一个例子,这里和为23,有两条路径[[5, 9, 6, 3], [5, 2, 1]]
5
/ \
2 9
/ \ / \
1 16 6 11
/
3
import copy
class Solution:
# 返回二维列表,内部每个列表表示找到的路径
def FindPath(self, root, expectNumber):
# write code here
if root == None:
return []
res = []
Array_list = [[root.val]] # 这个临时存储list路径是真的牛皮,服了!
temp = [root]
while temp:
node = temp.pop(0)
temp_list = Array_list.pop(0)
if node.left == None and node.right == None:
if sum(temp_list) == expectNumber:
res.insert(0, temp_list)
if node.left:
temp.append(node.left)
new_temp_list = copy.copy(temp_list) # # 这里的浅拷贝也非常好
new_temp_list.append(node.left.val)
Array_list.append(new_temp_list)
if node.right:
temp.append(node.right)
new_temp_list = copy.copy(temp_list)
new_temp_list.append(node.right.val)
Array_list.append(new_temp_list)
return res
二叉树搜索与双向链表
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
思路:
举例
5
/ \
2 9
/ \ / \
1 16 6 11
1)看图说话,你看因为是搜索二叉树,看两个子树比如
左子树 1<-2->16
右子树 6<-9->11
父节点 2<-5->9 (这里因为要构成双向链表明显不对,应该是16<-5->5)
2) 注意看,刚才的左右子树,只需要各个子节点比如 left=1 连向mid=2, right=16 连向 mid=2
3)但是顶部的父节点,明显是连接的左子树的 最右节点16, 右子树的最左节点6 才能构成双向链表
参考链接:https://blog.csdn.net/u010005281/article/details/79657259
# 二叉树中序遍历的方法
# 最基本的中序遍历复习一波
class Solution:
def __init__(self):
self.array = []
def mid_traval(self, root):
if not root:
return self.array
self.mid_traval(root.left)
self.array.append(root.val)
print(root.val)
self.mid_traval(root.right)
# 看看改进版,我都不知道他们怎么想到的
class Solution:
# write code here
def __init__(self):
self.listHead = None
self.listTail = None
def Convert(self, pRootOfTree):
if pRootOfTree == None:
return
self.Convert(pRootOfTree.left)
if self.listHead == None:
self.listHead = pRootOfTree
self.listTail = pRootOfTree
else:
self.listTail.right = pRootOfTree
pRootOfTree.left = self.listTail
self.listTail = pRootOfTree
self.Convert(pRootOfTree.right)
return self.listHead
# 来个正常人思路版本
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
# write code here
def Convert(self, pRootOfTree):
if pRootOfTree == None:
return None
left = self.Convert(pRootOfTree.left)
right = self.Convert(pRootOfTree.right)
start = left
# 这里如果是 左子树,找到它的最右的子节点,一会要连接中间节点
# 注意叶子节点的最右节点,最左节点是它本身
if left:
left = self.find_rightest(left)
left.right = pRootOfTree
else:
start = pRootOfTree # 这里解释,最后的叶子节点,后面的None也会进入递归,这里吧start给那个叶子节点,而不是None
pRootOfTree.left = left
pRootOfTree.right = right
if right:
right.left = pRootOfTree
return start
def find_rightest(self, node):
while node.right:
node = node.right
return node
return begin
if __name__ == "__main__":
t1 = TreeNode(4)
t2 = TreeNode(2)
t3 = TreeNode(6)
t4 = TreeNode(1)
t5 = TreeNode(3)
t6 = TreeNode(5)
t7 = TreeNode(7)
t1.left = t2
t1.right = t3
t2.left = t4
t2.right = t5
t3.left = t6
t3.right = t7
B = Solution2()
aa = B.Convert(t1)
a = 1
二叉树的下一个节点:
给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。
# -*- coding:utf-8 -*-
# class TreeLinkNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
# self.next = None
class Solution:
def GetNext(self, pNode):
# write code here
# 找规律的感觉,如果存在右子树,则找到右子树的最左节点,就是中序遍历的下一个节点
if pNode.right:
temp_node = pNode.right
while temp_node.left:
temp_node = temp_node.left
return temp_node
# 如果没有最右子树,那么就看这个节点A的父节点B,A是不是B的左节点,是就输出,否则继续再中序
# 遍历中继续下一个节点,这就是为什么题目说了有next这个东西
else:
temp_node = pNode
while temp_node.next:
if temp_node.next.left == temp_node:
return temp_node.next
temp_node = temp_node.next
return None
对称的二叉树:
请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def isSymmetrical(self, pRoot):
# write code here
# 主要思路2步: 1) 判断两个节点值是否相等,2)判断A节点的左节点值 == B节点的右节点值
# 边界条件, 头结点为空的时候,也算对称为True
if pRoot == None:
return True
return self.judge_node(pRoot.left, pRoot.right)
def judge_node(self, left, right):
# 递归的出口,最后的节点情况,注意这里是 left, right
if left == None and right == None:
return True
elif left == None or right == None:
return False
if left.val != right.val: # 判断A,B 节点
return False
res1 = self.judge_node(left.left, right.right) # 判断A,B下面子节点
res2 = self.judge_node(left.right, right.left)
return res1 and res2
按之字形顺序打印二叉树:
请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def Print(self, pRoot):
# write code here
# 需要用两个stack来保存不同的顺序,需要res来保存结果
# 注意append的顺序哦,stack1中节点的子节点保存到 stack2,append left ,right
# stack2中节点的子节点保存到 stack1 时候,是先append right,left 调试一下就知道了
# 二叉树如果长这样
# 1
# / \
# 2 3
# / \ / \
#4 5 6 7
# 那么 res 的变化是 [[1], [3, 2], [4, 5, 6, 7]]
if pRoot == None:
return []
res = []
stack1 = [pRoot]
stack2 = []
while stack1 or stack2:
if stack1:
temp_res = [] # 保存这行顺序的结果
while stack1:
temp_node = stack1.pop()
temp_res.append(temp_node.val)
if temp_node.left: # 注意不要把 None append 进去
stack2.append(temp_node.left) # 先append left
if temp_node.right:
stack2.append(temp_node.right) # 后append right
res.append(temp_res)
if stack2:
temp_res = []
while stack2:
temp_node = stack2.pop()
temp_res.append(temp_node.val)
if temp_node.right:
stack1.append(temp_node.right) # 先 right
if temp_node.left:
stack1.append(temp_node.left) # 后 left
res.append(temp_res)
return res
把二叉树打印成多行
从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。
class Solution:
# 返回二维列表[[1,2],[4,5]]
def Print(self, pRoot):
# write code here
if pRoot == None:
return []
res = []
stack1 = [pRoot]
stack2 = []
while stack1 or stack2:
if stack1:
temp_res = [] # 保存这行顺序的结果
while stack1:
temp_node = stack1.pop(0)
temp_res.append(temp_node.val)
if temp_node.left: # 注意不要把 None append 进去
stack2.append(temp_node.left) # 先append left
if temp_node.right:
stack2.append(temp_node.right) # 后append right
res.append(temp_res)
if stack2:
temp_res = []
while stack2:
temp_node = stack2.pop(0)
temp_res.append(temp_node.val)
if temp_node.left:
stack1.append(temp_node.left)
if temp_node.right:
stack1.append(temp_node.right)
res.append(temp_res)
return res
二叉搜索树第K小的节点
给定一棵二叉搜索树,请找出其中的第k小的结点。例如, (5,3,7,2,4,6,8) 中,按结点数值大小顺序第三小结点的值为4。
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
# 返回对应节点TreeNode
def KthNode(self, pRoot, k):
# write code here
# 注意 二叉搜索树的 中序遍历 就是有序数列
if pRoot == None:
return None
res = []
def mid_order(node):
if node == None:
return None
mid_order(node.left)
res.append(node)
mid_order(node.right)
mid_order(pRoot)
if k < 1 or k > len(res):
return None
return res[k-1]
序列化二叉树:
请实现两个函数,分别用来序列化和反序列化二叉树
二叉树的序列化是指:把一棵二叉树按照某种遍历方式的结果以某种格式保存为字符串,从而使得内存中建立起来的二叉树可以持久保存。序列化可以基于先序、中序、后序、层序的二叉树遍历方式来进行修改,序列化的结果是一个字符串,序列化时通过 某种符号表示空节点(#),以 ! 表示一个结点值的结束(value!)。
二叉树的反序列化是指:根据某种遍历顺序得到的序列化字符串结果str,重构二叉树。
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def Serialize(self, root):
res = []
def pre_order(root):
if root == None:
res.append("#")
return
res.append(str(root.val))
pre_order(root.left)
pre_order(root.right)
pre_order(root)
return " ".join(res)
# write code here
def Deserialize(self, s):
# write code here
res = s.split()
def depre_order():
if res == []:
return None
rootVal = res.pop(0)
if rootVal == "#":
return None
node = TreeNode(int(rootVal))
leftnode = depre_order()
rightnode = depre_order()
node.left = leftnode
node.right = rightnode
return node
pRoot = depre_order()
return pRoot
二叉树的深度:
输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def TreeDepth(self, pRoot):
# write code here
# 方法一:递归,注意返回值是return 0
#if pRoot == None:
#return 0
#left = self.TreeDepth(pRoot.left)
#right = self.TreeDepth(pRoot.right)
#return max(left, right) + 1
# 方法二:利用数据结构queue,pop(0)
if pRoot == None:
return 0
temp = [pRoot]
d, count = 0, 0
next_count = len(temp)
while len(temp) != 0:
node = temp.pop(0)
count += 1
if node.left:
temp.append(node.left)
if node.right:
temp.append(node.right)
if count == next_count:
d += 1
count = 0
next_count = len(temp)
return d