【树-02】树的题目解析
目录
- 剑指 Offer 54. 二叉搜索树的第k大节点
- 剑指 Offer 28. 对称的二叉树/101. 对称二叉树
- 剑指 Offer 32 - II. 从上到下打印二叉树 II/102. 二叉树的层序遍历
- 剑指 Offer 32 - III. 从上到下打印二叉树 III
- 剑指 Offer 32 - I. 从上到下打印二叉树
一、剑指 Offer 54. 二叉搜索树的第k大节点
1.1 问题
给定一棵二叉搜索树,请找出其中第k大的节点。
示例 1:
输入: root = [3,1,4,null,2], k = 1
3
/ \
1 4
\
2
输出: 4
示例 2:
输入: root = [5,3,6,2,4,null,null,1], k = 3
5
/ \
3 6
/ \
2 4
/
1
输出: 4
1.2 代码(使用递归)
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def kthLargest(self, root: TreeNode, k: int) -> int:
def dfs(root): #右根左的形式递归调用
if not root :
return
dfs(root.right)
if self.k == 0:
return
self.k -= 1
if self.k == 0:
self.res = root.val
dfs(root.left)
self.k = k #这个不能少,可以带入到dfs函数中,不能在下面带入函数中
dfs(root)
return self.res
1.3 代码(不用递归)
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def kthLargest(self, root: TreeNode, k: int) -> int:
stack = [] #右根左的形式入栈数据
p = root #用于指向当前节点
count = 0 #用于计算当前节点第几大
while p or stack:
while p:
stack.append(p)
p = p.right
if stack:
curr = stack.pop()
count += 1
if count == k:return curr.val
p = curr.left
二、剑指 Offer 28. 对称的二叉树/101. 对称二叉树
2.1 问题
请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。例如,二叉树 [1,2,2,3,4,4,3] 是对称的。
1
/ \
2 2
/ \ / \
3 4 4 3
但是下面这个 [1,2,2,null,3,null,3] 则不是镜像对称的:
1
/ \
2 2
\ \
3 3
示例 1:
输入:root = [1,2,2,3,4,4,3]
输出:true
示例 2:
输入:root = [1,2,2,null,3,null,3]
输出:false
2.2 代码一(递归实现)
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def isSymmetric(self, root: TreeNode) -> bool:
def dfs(t1, t2):
# 递归的终止条件是两个节点都为空
# 或者两个节点中有一个为空
# 或者两个节点的值不相等
if not(t1 or t2):
return True
if not(t1 and t2 ):
return False
return (t1.val == t2.val) and dfs(t1.right,t2.left) and dfs(t1.left , t2.right)
return dfs(root,root)
2.3 代码二(队列实现)
class Solution:
def isSymmetric(self, root: TreeNode) -> bool:
if not root or not(root.left or root.right):
return True
queue = [root.left,root.right]
while queue:
left = queue.pop()
right = queue.pop()
if not(left or right):#两个都为空,继续循环
continue
if not(left and right): #两个有一个不空,这False
return False
if left.val != right.val:
return False
# 将左节点的左孩子, 右节点的右孩子放入队列
queue.append(left.left)
queue.append(right.right)
# 将左节点的右孩子,右节点的左孩子放入队列
queue.append(left.right)
queue.append(right.left)
return True
三、剑指 Offer 32 - II. 从上到下打印二叉树 II/102. 二叉树的层序遍历
3.1 题目
从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。
例如:
给定二叉树: [3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
返回其层次遍历结果:
[
[3],
[9,20],
[15,7]
]
3.2 代码(BFS,按层次遍历)
class Solution:
def levelOrder(self, root: TreeNode) -> List[List[int]]:
if not root :
return []
res = []
queue = collections.deque()
queue.append(root)
while queue:
temp = []
for _ in range(len(queue)): #思路很好,虽然后面有加入,但是不影响目前层的遍历
node = queue.popleft() #要求从底部出去
temp.append(node.val)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
res.append(temp)
return res
四、剑指 Offer 32 - III. 从上到下打印二叉树 III
4.1 题目
请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推。
例如:
给定二叉树: [3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
返回其层次遍历结果:
[
[3],
[20,9],
[15,7]
]
4.2 代码(BFS,按层次遍历+双端队列,和上一题差不多)
class Solution:
def levelOrder(self, root: TreeNode) -> List[List[int]]:
if not root :
return []
res =[]
queue = collections.deque()
queue.append(root)
while queue:
temp = collections.deque()
for _ in range(len(queue)):
node = queue.popleft()
if len(res)%2: # 偶数层 -> 队列头部
temp.appendleft(node.val)
else:temp.append(node.val) # 奇数层 -> 队列尾部
if node.left :
queue.append(node.left)
if node.right:
queue.append(node.right)
res.append(list(temp)) #注意,这里需要用list
return res
五、剑指 Offer 32 - I. 从上到下打印二叉树
5.1 问题
从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印。
例如:
给定二叉树: [3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
返回:
[3,9,20,15,7]
5.2 代码(感觉这一题比上面两题要简单,但是标注为中)
class Solution:
def levelOrder(self, root: TreeNode) -> List[int]:
if not root : return []
res =[]
queue = collections.deque()
queue.append(root)
while queue:
for _ in range(len(queue)):
node = queue.popleft()
res.append(node.val)
if node.left :queue.append(node.left)
if node.right:queue.append(node.right)
return res
参考文献