文章目录
9 二叉树
9.1 【递归】二叉树的最大深度
递归找左子树和右子树的最大深度,就是二叉树的最大深度。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def maxDepth(self, root: Optional[TreeNode]) -> int:
if not root:
return 0
else:
left_depth = self.maxDepth(root.left)
right_depth = self.maxDepth(root.right)
return max(left_depth, right_depth) + 1
9.2 【递归】相同的树
题目地址:https://leetcode.cn/problems/same-tree/description/?envType=study-plan-v2&envId=top-interview-150
左右子树相同的标志是左右子树都存在,且根节点的值相等,按照这一标准递归遍历树的左右子树。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def isSameTree(self, p: Optional[TreeNode], q: Optional[TreeNode]) -> bool:
if (not p and q) or (p and not q):
return False
elif not p and not q:
return True
elif p.val != q.val:
return False
else:
return self.isSameTree(p.left,q.left) and self.isSameTree(p.right,q.right)
9.3 【递归】翻转二叉树
详见代码。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
if not root:
return
root.left,root.right = self.invertTree(root.right),self.invertTree(root.left)
return root
9.4 【递归】对称二叉树
详见代码。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def isSymmetric(self, root: Optional[TreeNode]) -> bool:
if not root:
return True
return self.is_symmetric(root.left, root.right)
def is_symmetric(self, left: TreeNode, right: TreeNode):
if not left and not right:
return True
elif (not left or not right) or (left.val != right.val):
return False
else:
return self.is_symmetric(left.left, right.right) and self.is_symmetric(left.right, right.left)
9.5 【递归】从前序与中序遍历序列构造二叉树
详见代码,找到根节点的位置进行递归。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
if not preorder or not inorder:
return
root = TreeNode(preorder[0])
idx = inorder.index(preorder[0])
root.left = self.buildTree(preorder[1:1+idx],inorder[:idx])
root.right = self.buildTree(preorder[1+idx:],inorder[idx+1:])
return root
9.6 【递归】从中序与后序遍历序列构造二叉树
详见代码,找到根节点的位置进行递归。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def buildTree(self, inorder: List[int], postorder: List[int]) -> Optional[TreeNode]:
if not inorder or not postorder:
return
root = TreeNode(postorder[-1])
idx = inorder.index(postorder[-1])
root.left = self.buildTree(inorder[:idx],postorder[:idx])
root.right = self.buildTree(inorder[1+idx:],postorder[idx:-1])
return root
9.7 【BFS】填充每个节点的下一个右侧节点指针 II
其实就是找出每一层的所有结点就行了,而每一层的左右节点就是下一层的结点,按照这个规则进行BFS。
"""
# Definition for a Node.
class Node:
def __init__(self, val: int = 0, left: 'Node' = None, right: 'Node' = None, next: 'Node' = None):
self.val = val
self.left = left
self.right = right
self.next = next
"""
class Solution:
def connect(self, root: 'Node') -> 'Node':
if not root:
return root
def BFS(curLayer):
nextLayer = []
for node in curLayer:
if node.left:
nextLayer.append(node.left)
if node.right:
nextLayer.append(node.right)
if len(nextLayer) > 1:
for i in range(0,len(nextLayer)-1):
nextLayer[i].next = nextLayer[i+1]
if nextLayer:
BFS(nextLayer)
BFS([root])
return root
9.8 【递归】二叉树展开为链表
二叉树的先序遍历的变形。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def flatten(self, root: Optional[TreeNode]) -> None:
"""
Do not return anything, modify root in-place instead.
"""
while root:
if root.left:
cur_left = root.left
while cur_left.right:
cur_left = cur_left.right
cur_left.right = root.right
root.right = root.left
root.left = None
root = root.right
9.9 【DFS】路径总和
题目地址:https://leetcode.cn/problems/path-sum/description/?envType=study-plan-v2&envId=top-interview-150
详见代码。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
if not root:
return False
elif not root.left and not root.right and targetSum == root.val:
return True
else:
return self.hasPathSum(root.left,targetSum-root.val) or self.hasPathSum(root.right,targetSum-root.val)
9.10 【DFS】求根节点到叶节点数字之和
DFS,分别从根节点计算每一条路径的数字,然后求和,这里要注意判断条件,当一个节点没有左节点和右节点时,说明这条路径到底了,这是要把目前的数字加入到 a n s ans ans中。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def sumNumbers(self, root: Optional[TreeNode]) -> int:
ans = 0
def sub_sum(root,cur_num):
nonlocal ans
if not root.left and not root.right:
ans += cur_num*10 + root.val
return
cur_num = cur_num*10 + root.val
if root.left:
sub_sum(root.left,cur_num)
if root.right:
sub_sum(root.right,cur_num)
sub_sum(root,0)
return ans
9.11 【BFS】【动态规划】二叉树中的最大路径和
先找到每个节点下的最大路径和,再一步步从上往下遍历所有节点,如果遍历到某个节点的左子树或者右子树的最大和小于零,则这个子树可以不要,只需考虑另一个子树即可。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def maxPathSum(self, root: Optional[TreeNode]) -> int:
self.maxSum = -1001
def BFS(root):
if not root:
return 0
left_max = BFS(root.left)
right_max = BFS(root.right)
self.maxSum = max(self.maxSum, left_max + right_max + root.val)
return max(0,max(left_max,right_max) + root.val)
BFS(root)
return self.maxSum
9.12 【BFS】二叉搜索树迭代器
先对二叉搜索树中的元素进行排序,然后按照题目要求构造函数即可。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class BSTIterator:
def __init__(self, root: Optional[TreeNode]):
self.root = root
self.num = []
self.idx = 0
self.len = 0
def BFS(root):
if not root:
return
self.num.append(root.val)
self.len += 1
BFS(root.left)
BFS(root.right)
BFS(root)
self.num.sort()
def next(self) -> int:
if self.idx < self.len:
self.idx += 1
return self.num[self.idx-1]
else:
return -1
def hasNext(self) -> bool:
if self.idx < self.len:
return True
else:
return False
# Your BSTIterator object will be instantiated and called as such:
# obj = BSTIterator(root)
# param_1 = obj.next()
# param_2 = obj.hasNext()
9.13 【BFS】完全二叉树的节点个数
详见代码。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def countNodes(self, root: Optional[TreeNode]) -> int:
self.ans = 0
def BFS(root):
if not root:
return
self.ans += 1
BFS(root.left)
BFS(root.right)
BFS(root)
return self.ans
9.14 【递归】二叉树的最近公共祖先
如果 p p p和 q q q位于二叉树的同一侧,那么最近公共祖先要么是 p p p要么是 q q q,如果位于二叉树的两侧,那么最近公共祖先则是两者最深的那个 r o o t root root。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
if not root or root == p or root == q:
return root
left = self.lowestCommonAncestor(root.left,p,q)
right = self.lowestCommonAncestor(root.right,p,q)
if not left:
return right
if not right:
return left
return root
10 二叉树层次遍历
10.1 【DFS】二叉树的右视图
深度优先遍历,每次都将二叉树每一层最右边的元素加入数组,同时设置 d e p t h depth depth来限制数组大小,保证数组中只有最右边的元素。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def rightSideView(self, root: Optional[TreeNode]) -> List[int]:
self.ans = []
def DFS(root, depth):
if not root:
return
if len(self.ans) < depth:
self.ans.append(root.val)
DFS(root.right, depth+1)
DFS(root.left, depth+1)
DFS(root, 1)
return self.ans
10.2 【BFS】二叉树的层平均值
详见代码。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def averageOfLevels(self, root: Optional[TreeNode]) -> List[float]:
ans = []
node_list = [root]
if not root:
return ans
while node_list:
cur_val = []
nxt_list = []
for node in node_list:
cur_val.append(node.val)
if node.left:
nxt_list.append(node.left)
if node.right:
nxt_list.append(node.right)
ans.append(sum(cur_val)/len(cur_val))
node_list = nxt_list
return ans
10.3 【BFS】二叉树的层序遍历
详见代码。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
ans = []
cur_node = [root]
if not root:
return ans
while cur_node:
cur_val = []
nxt_node = []
for node in cur_node:
cur_val.append(node.val)
if node.left:
nxt_node.append(node.left)
if node.right:
nxt_node.append(node.right)
ans.append(cur_val)
cur_node = nxt_node
return ans
10.4 【BFS】二叉树的锯齿形层序遍历
详见代码。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def zigzagLevelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
ans = []
cur_node = [root]
flag = True
if not root:
return ans
while cur_node:
cur_val = []
nxt_node = []
for node in cur_node:
cur_val.append(node.val)
if node.left:
nxt_node.append(node.left)
if node.right:
nxt_node.append(node.right)
if flag:
ans.append(cur_val)
else:
ans.append(cur_val[::-1])
flag = not flag
cur_node = nxt_node
return ans
11 二叉搜索树
11.1 【BFS】二叉搜索树的最小绝对差
先遍历所有节点,然后排序,找出相邻元素差值最小的。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def getMinimumDifference(self, root: Optional[TreeNode]) -> int:
self.num = []
def BFS(root):
if not root:
return
self.num.append(root.val)
BFS(root.left)
BFS(root.right)
BFS(root)
self.num.sort()
ans = 100001
for i in range(len(self.num)-1):
ans = min(ans,self.num[i+1]-self.num[i])
return ans
11.2 【BFS】二叉搜索树中第K小的元素
对于二叉搜索树而言,中序遍历就是其从小到大的排序结果,记录访问到的第 k k k个元素即可。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def kthSmallest(self, root: Optional[TreeNode], k: int) -> int:
self.k = k
self.ans = 0
def BFS(root):
if not root:
return
BFS(root.left)
self.k -= 1
if self.k == 0:
self.ans = root.val
return
BFS(root.right)
BFS(root)
return self.ans
11.3 【BFS】【递归】验证二叉搜索树
递归实现,首先要明白二叉搜索树的判定条件,一是左子树<root<右子树,二是下面的左子树的值要比当前结点小,而右子树的值要比当前结点大,也就是不能只在一个小的子树上满足这个条件,往上回溯几代之后这个条件要依然满足才行。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def isValidBST(self, root: Optional[TreeNode]) -> bool:
def is_Valid_BST(root, min_node, max_node):
if not root:
return True
else:
if min_node and root.val <= min_node.val:
return False
if max_node and root.val >= max_node.val:
return False
return is_Valid_BST(root.left, min_node, root) and is_Valid_BST(root.right, root, max_node)
return is_Valid_BST(root, None, None)