5 树
1.1 基础
树(Tree):由
n >= 0
个节点与节点之间的关系组成的有限集合。当n = 0
时称为空树,当n>0
时称为非空树。
-
树是一种特殊的图 >>> 无环联通图
-
可将树分为两种类型:「有序树」 和 「无序树」。
有序树:节点的各个⼦树从左⾄右有序, 不能互换位置。
无序树:节点的各个⼦树可互换位置。
- 二叉树
二叉树(Binary Tree):树中各个节点的度不大于 2 个的有序树,称为二叉树。通常树中的分支节点被称为 「左子树」 或 「右子树」。二叉树的分支具有左右次序,不能随意互换位置(有序)。
满二叉树(Full Binary Tree):如果所有分支节点都存在左子树和右子树,并且所有叶子节点都在同一层上,则称该二叉树为满二叉树。
完全二叉树(Complete Binary Tree):如果叶子节点只能出现在最下面两层,并且最下层的叶子节点都依次排列在该层最左边的位置上(对应满二叉),具有这种特点的二叉树称为完全二叉树。
二叉搜索树(Binary Search Tree):也叫做二叉查找树、有序二叉树或者排序二叉树。是指一棵空树或者具有下列性质的二叉树
- 如果任意节点的左子树不为空,则左子树上所有节点的值均小于它的根节点的值。
- 如果任意节点的右子树不为空,则右子树上所有节点的值均大于它的根节点的值。
- 任意节点的左子树、右子树均为二叉搜索树。
平衡二叉搜索树(Balanced Binary Tree):一种结构平衡的二叉搜索树。即叶节点高度差的绝对值不超过 1,并且左右两个子树都是一棵平衡二叉搜索树。平衡二叉树可以在 内完成插入、查找和删除操作。最早被发明的平衡二叉搜索树为 「AVL 树(Adelson-Velsky and Landis Tree))」。
1.2 题目
1.2.1 104 . 二叉树的最大深度
- 1.DFS后序 >>> 左右 根
(depth + 1)
class Solution:
def maxDepth(self, root: Optional[TreeNode]) -> int:
# 后序dfs
if not root:
return 0
ans = max(self.maxDepth(root.left), self.maxDepth(root.right)) + 1
return ans
- 2.DFS前序 >>> 根左右
class Solution:
def maxDepth(self, root: Optional[TreeNode]) -> int:
# 先序dfs
self.ans = 0
depth = 0
self.dfs(root, depth, self.ans)
return self.ans
def dfs(self, root, depth, ans):
if not root:
self.ans = max(self.ans, depth)
return
depth += 1
self.dfs(root.left, depth, self.ans)
self.dfs(root.right, depth, self.ans)
- 3.BFS >>> 分层访问
class Solution:
def maxDepth(self, root: Optional[TreeNode]) -> int:
if not root:return 0
depth,q = 0, collections.deque()
q.append(root)
while q:
depth += 1
for i in range(len(q)):
temp = q.popleft()
if temp.left:
q.append(temp.left)
if temp.right:
q.append(temp.right)
return depth
1.2.2 108 . 将有序数组转换为二叉搜索树
- 思路: 利用二叉搜索树的中序遍历必然为一个有序序列性质 >> 以有序数组为中序 >>> 以中间元素为根节点并递归
class Solution:
def sortedArrayToBST(self, nums: List[int]) -> TreeNode:
def bulidBST(l, r):
if l > r:return
mid = l + (r - l) // 2
new_root = TreeNode(nums[mid])
new_root.left = bulidBST(l, mid - 1)
new_root.right = bulidBST(mid + 1, r)
return new_root
return bulidBST(0, len(nums) - 1)
1.2.3 111 . 二叉树的最小深度
1.DFS后序 >>>> 题目限制需要走到叶子节点 >>> 在最大深度基础上加条件即可
class Solution:
def minDepth(self, root: TreeNode) -> int:
if not root:return 0
l, r = self.minDepth(root.left), self.minDepth(root.right) #加快运算效率
if not l:return r + 1 #左无子看右
if not r:return l + 1 #右无子看左
return min(l, r) + 1
2.BFS >>> 增加到叶子返回深度条件即可
class Solution:
def minDepth(self, root: TreeNode) -> int:
if not root:return 0
depth, q = 0, collections.deque()
q.append(root)
while q:
depth += 1
for i in range(len(q)):
cur = q.popleft()
if not cur.left and not cur.right: #到叶子
return depth
if cur.left:
q.append(cur.left)
if cur.right:
q.append(cur.right)
return depth
1.2.4 112 . 路径总和
- 思路:
1.DFS >>> 利用target -root.val
遍历左右子树, 查找到根节点最后是否存在target == root.val
class Solution:
def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
if not root:return False #边界1
if not root.left and not root.right: #边界2 确定到根节点
return root.val == targetSum
return self.hasPathSum(root.left, targetSum - root.val) or self.hasPathSum(root.right, targetSum - root.val)
2.BFS
class Solution:
def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
if not root:return False
q = collections.deque()
q.append((root, root.val))
while q:
cur, target = q.popleft()
if not cur.left and not cur.right and target == targetSum:
return True
if cur.left:
q.append((cur.left, cur.left.val + target))
if cur.right:
q.append((cur.right, cur.right.val + target))
return False
1.2.5 173 . 二叉搜索树迭代器
- 思路: 利用中序性质即可
class BSTIterator:
def __init__(self, root: TreeNode):
self.stack = []
self.index = -1
def Inorder(root):
if root:
Inorder(root.left)
self.stack.append(root.val)
Inorder(root.right)
Inorder(root)
def next(self) -> int:
self.index += 1
return self.stack[self.index]
def hasNext(self) -> bool:
return len(self.stack) - 1 > self.index