树的递归遍历----深度优先搜索
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
preorder---中左右
postorder---左右中
inorder---左中右
144. Binary Tree Preorder Traversal
class Solution:
def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
if root == None:
return []
return self.postorderTraversal(root.left) + self.postorderTraversal(root.right) + [root.val]
层序遍历----广度优先搜索
102. Binary Tree Level Order Traversal
二叉树本身的结构做不到,借助--队列--数据结构
tip: 数组元素倒叙输出:res[::-1]
class Solution:
def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
if root is None:
return []
# 1. 建一个队列,并把root放进去
queue = collections.deque([root])
result = [] # 最终结果
while queue:
# 2. 大循环----一层一个循环
level = []
size = len(queue)
# 3. 小循环:
# a. queue最左边的元素pop
# b. append进level
# c. 该元素的左右孩子add进queue
# 结束: size为0
while size:
cur = queue.popleft()
level.append(cur.val)
if cur.left:
queue.append(cur.left)
if cur.right:
queue.append(cur.right)
size -= 1
result.append(level)
return result
104. Maximum Depth of Binary Tree
层序遍历法
翻转二叉树
将当前节点的左右child调换
选择前序遍历
class Solution:
def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
if root is None:
return None
# preorder
# 中
root.left, root.right = root.right, root.left
# 左
self.invertTree(root.left)
# 右
self.invertTree(root.right)
return root
对称二叉树
后序遍历---通过左右孩子的情况反馈给root
对当前root,它的左右子树是对称的---> 返回给root true的信息
怎么判断左右子树对称:left.left和right.right一样, left.right和right.left一样
class Solution:
def isSymmetric(self, root: Optional[TreeNode]) -> bool:
if root is None:
return True
return self.compare(root.left, root.right)
def compare(self, left, right):
# 比较某个root的左子树是不是和右子树对称,返回bool
# 其实每次就是判断传入的left和right值是不是相等,递归中不断传入需要接下来判断的左右值
# 1 左空右空
if left is None and right is None:
return True
# 2 左空右不空
elif left is None and right is not None:
return False
# 3 左不空右空
elif left is not None and right is None:
return False
# 4 左不空右不空
# 4.1 左 != 右
elif left.val != right.val:
return False
# 4.2 左 == 右
# (left.val == right.val) 当前是true,继续递归
outside = self.compare(left.left, right.right)
inside = self.compare(left.right, right.left)
return outside and inside
二叉树的最大深度
104. Maximum Depth of Binary Tree
class Solution:
def maxDepth(self, root: Optional[TreeNode]) -> int:
if root is None:
return 0
# 左右中
left = self.maxDepth(root.left)
right = self.maxDepth(root.right)
return 1 + max(left, right)
二叉树的最小深度
根节点到最近的叶子节点的距离
111. Minimum Depth of Binary Tree
class Solution:
def minDepth(self, root: Optional[TreeNode]) -> int:
if root is None:
return 0
# 左右中
left = self.minDepth(root.left)
right = self.minDepth(root.right)
# 为了避免一种情况---root的左子树为空时,该边不算做depth的考虑范围
if root.left is None and root.right != None:
return 1 + right
if root.right is None and root.left != None:
return 1 + left
return 1 + min(left, right)
完全二叉树
左子树节点数量 + 右子树节点数量 + 1---------适用于任何一个BST
222. Count Complete Tree Nodes
class Solution:
def countNodes(self, root: Optional[TreeNode]) -> int:
if root is None:
return 0
return self.countNodes(root.left) + self.countNodes(root.right) + 1
平衡二叉树
def maxDepth------左右中的遍历顺序,在递归中不断得到子树的高度,并判断每一个当前root的左右子树差是不是符合标准
信息是由left和right反馈给root
只要当前某一个root不符合了,就给标记一个-1,这个root可能是前一次递归的某个左子树或右子树,所以在递归中只要left/right的值碰到了-1,向根节点也反馈的是-1的信息
class Solution:
def isBalanced(self, root: Optional[TreeNode]) -> bool:
if root is None:
return True
if self.maxDepth(root) == -1:
return False
return True
def maxDepth(self, root):
if root is None:
return 0
left = self.maxDepth(root.left)
if left == -1:
return -1
right = self.maxDepth(root.right)
if right == -1:
return -1
# 当发现任何一个当前节点的左右子树高度差超过1的时候,该树已经不可能符合了
if abs(left - right) > 1:
return -1
else:
return max(left, right) + 1
173. Binary Search Tree Iterator
全局变量---在init中命名,可以整个class调用的
class BSTIterator:
def __init__(self, root: Optional[TreeNode]):
# inorder---左中右
arr = self.inorder(root)
print(arr)
def inorder(self, root):
if not root:
return []
return self.inorder(root.left) + [root.val] + self.inorder(root.right)
def next(self) -> int:
def hasNext(self) -> bool:
# Your BSTIterator object will be instantiated and called as such:
# obj = BSTIterator(root)
# param_1 = obj.next()
# param_2 = obj.hasNext()
tree的回溯
回溯: 先收集1,2,5;弹出2,5加入3
弹出2,5的过程就是回溯
回溯中使用全局变量---其他def可以调用并且随着不断递归执行def,该变量一直在更新
self.res.append(self.path[:]) ------coy path,收集路径的时候self.path[:]可以让path的变化不影响res
.join()的使用: ‘->'.join(list) # 将list中的所有元素用->相连接,此处的list应为str数组
map(str, path): 将int型数组转化为str数组、
class Solution:
def __init__(self):
self.path = []
self.res = []
def binaryTreePaths(self, root: Optional[TreeNode]) -> List[str]:
if root is None:
return []
self.traversal(root)
return self.res
def traversal(self, cur):
# 前序--中左右
self.path.append(cur.val)
# 递归的终止条件---遍历到leaf
if cur.left is None and cur.right is None:
new_path = "->".join(map(str, self.path[:]))
self.res.append(new_path) # 收集该条路径
return
if cur.left:
self.traversal(cur.left)
self.path.pop()
if cur.right:
self.traversal(cur.right)
self.path.pop()
左子树叶子合
class Solution:
def sumOfLeftLeaves(self, root: Optional[TreeNode]) -> int:
# 对于每一个root----结果为root.left的ans和root.right的ans----由左右子树的结果得到root的结果----左右中
if root is None:
return 0
if root.left is None and root.right is None:
return 0
left = self.sumOfLeftLeaves(root.left) # 左
if root.left and root.left.left is None and root.left.right is None:
left = root.left.val
right = self.sumOfLeftLeaves(root.right) # 右
ans = left + right # 中
return ans
思路:确定root---确定root.left----确定root.right
class Solution:
def constructMaximumBinaryTree(self, nums: List[int]) -> Optional[TreeNode]:
if len(nums) == 1:
return TreeNode(nums[0])
root = TreeNode(max(nums))
max_index = nums.index(max(nums))
left = nums[:max_index]
if len(left) != 0:
root.left = self.constructMaximumBinaryTree(left)
right = nums[max_index+1:]
if len(right) != 0:
root.right = self.constructMaximumBinaryTree(right)
return root
合并二叉树
class Solution:
def mergeTrees(self, root1: Optional[TreeNode], root2: Optional[TreeNode]) -> Optional[TreeNode]:
# root1 root2都不空----直接相加
# root1空
# root2空
if not root1: # 如果root1空
return root2
if not root2:
return root1
root = TreeNode(root1.val + root2.val)
root.left = self.mergeTrees(root1.left, root2.left)
root.right = self.mergeTrees(root1.right, root2.right)
return root
BST
700. Search in a Binary Search Tree
搜索思路:val比root大就向右搜索,小就向左搜索
终止条件就是:要么找到val了就停,要么遍历完还是没找到也停
返回值---当前的节点,treenode
class Solution:
def searchBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
# 递归终止条件:
if root is None:
return root
if root.val == val:
return root
if root.val > val:
# 向左遍历
cur = self.searchBST(root.left, val)
if root.val < val:
cur = self.searchBST(root.right, val)
return cur
98. Validate Binary Search Tree
方法一:先写成inorder的数组形式,判断数组是不是单调递增
方法二:直接inorder遍历判断-----左中右
所谓的中就是对当前节点进行操作---本题中就是判断每次的val是不是递增的
递归返回值是bool
530. Minimum Absolute Difference in BST
class Solution:
def __init__(self):
self.res = float('inf')
self.pre = None # pre记录上一次的cur
# 如果不用全局变量,每次执行def traversal,pre都被初始化为null, 记录不了上一次的cur
def getMinimumDifference(self, root: Optional[TreeNode]) -> int:
self.traversal(root)
return self.res
def traversal(self, cur):
if cur is None:
return
self.traversal(cur.left)
if self.pre is not None:
self.res = min(self.res, abs(cur.val - self.pre.val))
self.pre = cur
self.traversal(cur.right)
501. Find Mode in Binary Search Tree
class Solution:
def __init__(self):
self.res = {}
def findMode(self, root: Optional[TreeNode]) -> List[int]:
ans = []
self.traversal(root)
max_count = max(self.res.values())
for j,i in self.res.items():
if i == max_count:
ans.append(j)
return ans
def traversal(self, cur):
if cur is None:
return
self.traversal(cur.left)
if cur.val in self.res.keys():
self.res[cur.val] += 1
else:
self.res[cur.val] = 1
self.traversal(cur.right)
701. Insert into a Binary Search Tree
class Solution:
def insertIntoBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
# 最底层---找到目标
if root is None:
node = TreeNode(val)
return node
if root.val < val:
root.right = self.insertIntoBST(root.right, val)
if root.val > val:
root.left = self.insertIntoBST(root.left, val)
return root
class Solution:
def deleteNode(self, root: Optional[TreeNode], key: int) -> Optional[TreeNode]:
# 1. 没找到
# 2. 没有左右child,直接delete
# 3. 左右都有child,右替换,左连接到右边根节点的左孩子上,返回右root
# 4. 左有,右没有,和左替换,返回左root
# 5. 右有,左没有,和右替换,返回右root
if root is None:
return root
# 底层找到目标
if root.val == key:
if root.left is None and root.right is None:
return None
elif root.left is None and root.right is not None:
return root.right
elif root.left is not None and root.right is None:
return root.left
else:
cur = root.right
while cur.left is not None:
cur = cur.left
cur.left = root.left
return root.right
if root.val > key:
root.left = self.deleteNode(root.left, key)
if root.val < key:
root.right = self.deleteNode(root.right, key)
return root
669. Trim a Binary Search Tree
公共祖先
236. Lowest Common Ancestor of a Binary Tree
思路: 从底层向上遍历-----回溯-----左右中方便回溯
代码思路:对于某一个节点root来说,root.left 和root.right都
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
if root is None:
return root
if root is p or root is q:
return root
left = self.lowestCommonAncestor(root.left, p, q)
right = self.lowestCommonAncestor(root.right, p, q)
if left and right:
return root
if left is None and right is not None:
return right
if right is None and left is not None:
return left
235. Lowest Common Ancestor of a Binary Search Tree
递归函数有返回值:
遍历单支----判断递归函数返回的不为空就直接return
遍历整支----left = , right = , left和right的逻辑判断
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
# 从上到下的遍历
if root == None:
return root
# 遍历左支
if root.val > q.val and root.val > p.val:
left = self.lowestCommonAncestor(root.left, p, q)
if left is not None:
return left
# 遍历右支
if root.val < q.val and root.val < p.val:
right = self.lowestCommonAncestor(root.right, p, q)
if right is not None:
return right
# 最底层的返回---找到目标
return root