前言
- 元宵节快乐 ~ 周六在图书馆快乐刷题!继续二叉树🍴
543. 二叉树的直径 - 力扣(LeetCode)
-
递归后序
-
class Solution: def diameterOfBinaryTree(self, root: Optional[TreeNode]) -> int: self.res = 0 # 记录最长路径 # 递归求最大深度 def depth(node): if not node: return 0 l = depth(node.left) # 左子树最大深度 r = depth(node.right) # 右子树最大深度 self.res = max(self.res, l + r) # 两边深度相加就是最长路径 return max(l, r) + 1 # 返回当前最大深度 depth(root) return self.res
-
108. 将有序数组转换为二叉搜索树 - 力扣(LeetCode)
-
递归前序
-
class Solution: def sortedArrayToBST(self, nums: List[int]) -> Optional[TreeNode]: def helper(left, right): if left > right: return # left == right也可以返回一个结点 mid = (left + right) // 2 root = TreeNode(nums[mid]) # 构造根节点 root.left = helper(left, mid-1) # 比根节点小的为左子树 root.right = helper(mid+1, right) # 比根节点大的为右子树 return root return helper(0, len(nums)-1)
-
98. 验证二叉搜索树 - 力扣(LeetCode)
-
递归BST
- 容易忽略上下界问题,详看题解
-
class Solution: def isValidBST(self, root: Optional[TreeNode]) -> bool: # 递归判断当前结点的值是否在上下界内 def helper(node, minVal, maxVal): if not node: return True # 每个节点如果超过这个范围,直接返回false if node.val >= maxVal or node.val <= minVal: return False # 左子树范围的最小值是minVal,最大值是当前节点的值,因为左子树的值要比当前节点小 l = helper(node.left, minVal, node.val) # 右子树范围的最大值是maxVal,最小值是当前节点的值,因为右子树的值要比当前节点大 r = helper(node.right, node.val, maxVal) return l and r # 初始上下界无限大,python用浮点数表示整数最大最小 return helper(root, -float('inf'), float('inf'))
-
递归中序
-
class Solution: # def __init__(self): # self.pre = None # 公共变量 def isValidBST(self, root: Optional[TreeNode]) -> bool: self.pre = None # 私有变量,记录上一个结点 def helper(root): if not root: return True l = helper(root.left) # 左 if self.pre and self.pre.val >= root.val: return False # 中 self.pre = root r = helper(root.right) # 右 return l and r return helper(root)
-
-
迭代中序
-
class Solution: def isValidBST(self, root: Optional[TreeNode]) -> bool: if not root: return True st = [] pre = -float('inf') while st or root: while root: st.append(root) root = root.left temp = st.pop() if temp.val <= pre: return False pre = temp.val root = temp.right return True
-
230. 二叉搜索树中第K小的元素 - 力扣(LeetCode)
-
迭代中序
-
class Solution: def kthSmallest(self, root: Optional[TreeNode], k: int) -> int: st = [] while st or root: while root: st.append(root) root = root.left temp = st.pop() k -= 1 if k == 0: return temp.val # 遍历到第k个结点 root = temp.right
-
-
优化查找
-
# 扩展TreeNode class TreeNode: def __init__(self, val=0, left=None, right=None): self.val = val self.left = left self.right = right self.node_num = 0 # 以该结点为根结点的子树的结点数 # 构造可供查找的MyBst类 class MyBst: def __init__(self, root: TreeNode): self.root = root self._count_node_num(root) # 初始化时计算每个结点为根结点的子树的结点数 def kth_smallest(self, k: int): node = self.root while node: left = node.left.node_num if node.left else 0 # 获取左子树的结点数 if left < k - 1: node = node.right # 移动到右子树查找 k -= left + 1 # 更新 k 值 elif left == k - 1: return node.val # 当前结点即为第 k 小的结点 else: node = node.left # 移动到左子树查找 def _count_node_num(self, node) -> int: if not node: return 0 # 递归计算以当前结点为根结点的子树的结点数 node.node_num = 1 + self._count_node_num(node.left) + self._count_node_num(node.right) return node.node_num # 返回以当前结点为根结点的子树的结点数 class Solution: def kthSmallest(self, root: TreeNode, k: int) -> int: bst = MyBst(root) return bst.kth_smallest(k) # 调用 MyBst 类的方法来找出第 k 小的结点的值
-
199. 二叉树的右视图 - 力扣(LeetCode)
-
迭代层序BFS
-
class Solution: def rightSideView(self, root: Optional[TreeNode]) -> List[int]: if not root: return [] res = [] q = deque() q.append(root) while q: n = len(q) # 先存长度以防变化 for i in range(n): cur = q.popleft() if cur.left: q.append(cur.left) if cur.right: q.append(cur.right) if i == n - 1: # 本层最后一个结点 res.append(cur.val) return res
-
-
递归逆先序DFS
-
# 思路类似【层序遍历】的 DFS递归 class Solution: def rightSideView(self, root: Optional[TreeNode]) -> List[int]: self.res = [] # 传入层当前深度 def dfs(root, depth): if not root: return if depth == len(self.res): self.res.append(root.val) # 中 dfs(root.right, depth + 1) # 右 dfs(root.left, depth + 1) # 左 dfs(root, 0) return self.res
-
后言
-
刷简单的二叉树题就是爽,递归的代码简短可以一次AC,还有精力去理解别的解法!多亏了之前刷代码随想录打的基础,感觉多刷一两次就可以看到就写出来了!刷二叉树信心MAX