# 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 inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
# # 递归 中序遍历 左根右
# res = []
# if not root:
# return res
# def dfs(node):
# if node.left:
# dfs(node.left)
# res.append(node.val)
# if node.right:
# dfs(node.right)
# return
# dfs(root)
# return res
# 迭代 中序遍历 左根右
res = []
stack = []
while root or len(stack) > 0:
# 遍历左节点,放入栈
while root:
stack.append(root)
root = root.left
# 中间处理
root = stack.pop()
# print(root.val)
res.append(root.val)
# 遍历右节点
root = root.right
return res
# 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 __init__(self):
self.preNode = float("-inf")
def isValidBST(self, root: Optional[TreeNode]) -> bool:
if not root:
return True
# # 返回是否是二叉搜索树
# # 递归时传入当前树的最小值和最大值
# # 左子树小于根节点,递归左子树,最小值需要继承,最大值就是根节点值
# # 右子树大于根节点,递归右子树,最大值需要继承,最小值就是根节点值
# def isValid(node, min_val, max_val):
# if not node:
# return True
# return node.val < max_val and node.val > min_val and isValid(node.left, min_val, node.val) and isValid(node.right, node.val, max_val)
# return isValid(root.left, float('-inf'), root.val) and isValid(root.right, root.val, float('inf'))
# # 中序遍历 二叉搜索树中序遍历是递增的
# # 返回 node 树是否满足中序遍历递增
# def dfs(node):
# if not node:
# return True
# res = dfs(node.left)
# # 中间位置加入判断逻辑
# # print(node.val)
# if node.val > self.preNode:
# self.preNode = node.val
# else:
# return False
# res = res and dfs(node.right)
# return res
# return dfs(root)
# 迭代 中序遍历 左根右
res = []
stack = []
preNode = float('-inf')
while root or len(stack) > 0:
# 遍历左节点,放入栈
while root:
stack.append(root)
root = root.left
# 中间处理
root = stack.pop()
if root.val > preNode:
preNode = root.val
else:
return False
# 遍历右节点
root = root.right
return True
# 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 recoverTree(self, root: Optional[TreeNode]) -> None:
"""
Do not return anything, modify root in-place instead.
"""
# 中序遍历,找到不符合递增关系的两个位置,重新遍历修改节点值
res = [] # 中序遍历结果
def dfs(node):
if not node:
return
dfs(node.left)
res.append(node.val)
dfs(node.right)
dfs(root)
# 找到不符合递增关系的位置 值
x, y = float('inf'), float('inf')
for i in range(1, len(res)):
if res[i] < res[i-1]:
y = res[i]
if x == float('inf'):
x = res[i-1]
else:
break
print(x, y)
# 重新遍历修改节点值
def dfs_re(node, x, y):
if not node:
return
dfs_re(node.left, x, y)
if node.val == x:
node.val = y
elif node.val == y:
node.val = x
dfs_re(node.right, x, y)
dfs_re(root, x, y)
return
# 维护 pre 节点,遍历过程中直接找到异常节点
# Morris 中序遍历
# 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: TreeNode, q: TreeNode) -> bool:
if not p and not q:
return True
if not p or not q:
return False
return p.val == q.val and self.isSameTree(p.left, q.left) and self.isSameTree(p.right, q.right)
# 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
def helper(left, right):
if not left and not right:
return True
if not left or not right:
return False
return left.val == right.val and helper(left.left, right.right) and helper(left.right, right.left)
return helper(root.left, root.right)
# 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
return max(self.maxDepth(root.left), self.maxDepth(root.right)) + 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 hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
if not root:
return False
def helper(node, targetSum):
if not node.left and not node.right and node.val == targetSum:
return True
is_left, is_right = False, False
if node.left:
is_left = helper(node.left, targetSum - node.val)
if node.right:
is_right = helper(node.right, targetSum - node.val)
return is_left or is_right
return helper(root, targetSum)
# if not root:
# return False
# if not root.left and not root.right:
# return sum == root.val
# return self.hasPathSum(root.left, sum - root.val) or self.hasPathSum(root.right, sum - root.val)
# 广度优先搜索
# 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 pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]:
# 回溯
res = []
ans = []
if not root:
return res
def dfs(node, target):
# 边界条件,达到叶子节点,满足条件的 ans 写入 res
if not node.left and not node.right and node.val == target:
ans.append(node.val)
res.append(ans[:]) # 注意 ans[:], 不能是 res.append(ans)
return
ans.append(node.val)
# 做选择,结果写入 ans
if node.left:
dfs(node.left, target - node.val)
# 退出选择,回到根节点
ans.pop()
if node.right:
dfs(node.right, target - node.val)
# 退出选择,回到根节点
ans.pop()
dfs(root, targetSum)
return res
# 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 __init__(self):
self.pre = None
def flatten(self, root: TreeNode) -> None:
"""
Do not return anything, modify root in-place instead.
"""
# # 递归,按照先序遍历的倒序进行遍历,处理根节点时,把左节点置 None,右节点置为 pre,更新 pre
# if not root:
# return
# self.flatten(root.right)
# self.flatten(root.left)
# # 处理根节点
# root.left = None
# root.right = self.pre
# self.pre = root
# return
# 迭代,找到左子树最右节点pre,把右子树接到 pre 右节点上,左子树放到右子树,左子树置 None
while root:
if not root.left:
root = root.right
continue
# 找到左子树最右节点pre
pre = root.left
while pre.right:
pre = pre.right
pre.right = root.right # 右子树接到 pre 右节点上
root.right = root.left # 左子树放到右子树
root.left = None # 左子树置 None
"""
# 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: 'Optional[Node]') -> 'Optional[Node]':
# # BFS 层序遍历
# if not root:
# return None
# level = 0
# queue = [root]
# while len(queue):
# size = len(queue)
# while size:
# cur = queue.pop(0)
# # 填充逻辑
# if cur and size > 1:
# cur.next = queue[0]
# #
# if cur.left:
# queue.append(cur.left)
# if cur.right:
# queue.append(cur.right)
# size -= 1
# level += 1
# return root
# 层序遍历,第 N 层处理第 N+1 层连接
if not root:
return None
# 最左侧节点,表示该层开始
left_most = root
# 只要下一层有节点,就遍历
while left_most.left:
# 遍历第 N 层节点
head = left_most
while head:
# 连接左节点和右节点
head.left.next = head.right
# 连接右节点和下一个的左节点
if head.next:
head.right.next = head.next.left
# 第 N 层 下一个节点
head = head.next
left_most = left_most.left
return 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 __init__(self):
self.res = 0
self.ans = 0
def sumNumbers(self, root: TreeNode) -> int:
# # dfs, 回溯,记录所有根节点到叶节点路径,同时计算路径数字
# if not root:
# return 0
# def dfs(node):
# self.ans = self.ans * 10 + node.val
# # 截止条件
# if not node.left and not node.right:
# self.res += int(self.ans)
# return
# # 做选择
# if node.left:
# dfs(node.left)
# # 退出选择
# self.ans = (self.ans - node.left.val) / 10
# if node.right:
# dfs(node.right)
# # 退出选择
# self.ans = (self.ans - node.right.val) / 10
# dfs(root)
# return self.res
# dfs 遍历一遍节点
if not root:
return self.res
def dfs(node, preSum):
# 截止条件
if not node:
return
# 计算该节点对应的数字
preSum = preSum * 10 + node.val
# 判断是否叶子节点,加到 result 中
if not node.left and not node.right:
self.res += preSum
# 递归左右节点
dfs(node.left, preSum)
dfs(node.right, preSum)
dfs(root, 0)
return self.res
class Solution:
def solve(self, board: List[List[str]]) -> None:
"""
Do not return anything, modify board in-place instead.
"""
# dfs,遍历边界字符,深度递归,找到所有与边界相连的‘O’,标记
# 重新遍历整个数组,替换未被标记的‘O’
m = len(board)
n = len(board[0])
def dfs(i, j):
# 边界条件
if i >= m or j >= n or i < 0 or j < 0 or board[i][j] != 'O':
return
# 标记
board[i][j] = '1'
# 寻找相邻字符‘O’
dfs(i, j+1)
dfs(i, j-1)
dfs(i-1, j)
dfs(i+1, j)
return
# 遍历第一行和最后一行,找到字符‘O’,进入递归,标记
# 处理首尾行
for j in range(0, n):
dfs(0, j)
dfs(m-1, j)
# 处理首尾列
for i in range(0, m-1):
dfs(i, 0)
dfs(i, n-1)
# 标记结束,重新遍历,替换未被标记的‘O’
for i in range(m):
for j in range(n):
if board[i][j] == '1':
board[i][j] = 'O'
elif board[i][j] == 'O':
board[i][j] = 'X'
return
# 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 preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
# # 递归
# res = []
# def preorder(root):
# if not root:
# return
# res.append(root.val)
# preorder(root.left)
# preorder(root.right)
# preorder(root)
# return res
# 迭代,借助一个 stack
res = []
stack = []
if not root:
return res
stack.append(root)
while len(stack):
cur = stack.pop()
res.append(cur.val)
if cur.right:
stack.append(cur.right)
if cur.left:
stack.append(cur.left)
return res
# 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 postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
# # 递归
# res = []
# def postorder(node):
# if not node:
# return
# postorder(node.left)
# postorder(node.right)
# res.append(node.val)
# postorder(root)
# return res
# # 迭代,借助两个 stack,先根右左,再左右根
# if not root:
# return []
# res = [] # 存放顺序 左右根
# stack1 = []
# stack2 = [] # 存放顺序 根右左
# stack1.append(root)
# while len(stack1):
# cur = stack1.pop()
# stack2.append(cur.val)
# if cur.left:
# stack1.append(cur.left)
# if cur.right:
# stack1.append(cur.right)
# while len(stack2):
# res.append(stack2.pop())
# return res
# 迭代
if not root:
return []
res = []
stack = []
prev = None
while root or len(stack):
while root:
stack.append(root)
root = root.left
root = stack.pop()
# 判断右子树是否空 或者 是否已经访问过
if not root.right or prev == root.right:
res.append(root.val)
prev = root
root = None
else:
# 没访问过,继续访问右子树
stack.append(root)
root = root.right
return res
# 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]:
# 层次遍历,打印每层最后一个
res = []
if not root:
return res
queue = []
queue.append(root)
while len(queue):
size = len(queue)
while size:
cur = queue.pop(0)
# 是否是每层最后一个元素
if size == 1:
res.append(cur.val)
if cur.left:
queue.append(cur.left)
if cur.right:
queue.append(cur.right)
size -= 1
return res
力扣
class Solution:
def numIslands(self, grid: List[List[str]]) -> int:
# dfs
def dfs(i, j):
# base case
if not inArea(i, j):
return
grid[i][j] = 2 # 标记为已访问
dfs(i-1, j)
dfs(i+1, j)
dfs(i, j-1)
dfs(i, j+1)
return
def inArea(i, j):
if i >=0 and j >= 0 and i < len(grid) and j < len(grid[0]) and grid[i][j] == '1':
return True
res = 0
for i in range(len(grid)):
for j in range(len(grid[0])):
if grid[i][j] == '1':
dfs(i, j)
res += 1
return res
class Solution:
def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
# 广度优先搜索
# 构建邻接表 & 入度数组
course = [[] for _ in range(numCourses)]
indegree = [0 for _ in range(numCourses)]
for item in prerequisites:
course[item[1]].append(item[0])
indegree[item[0]] += 1
# 选课队列,挑选入度为 0 入队
queue = []
for i in range(numCourses):
if indegree[i] == 0:
queue.append(i)
# 选出一门课,遍历邻居,更新 indegree
count = 0 # 选课数
while len(queue):
cur = queue.pop(0)
count += 1
for c in course[cur]:
indegree[c] -= 1 # 更新入度
if indegree[c] == 0:
queue.append(c)
return count == numCourses
class Solution:
def findOrder(self, numCourses: int, prerequisites: List[List[int]]) -> List[int]:
# 广度优先搜索
# 构建邻接表 & 入度数组
course = [[] for _ in range(numCourses)]
indegree = [0 for _ in range(numCourses)]
for item in prerequisites:
course[item[1]].append(item[0])
indegree[item[0]] += 1
# 选课队列,挑选入度为 0 入队
queue = []
for i in range(numCourses):
if indegree[i] == 0:
queue.append(i)
# 选出一门课,遍历邻居,更新 indegree
res = []
while len(queue):
cur = queue.pop(0)
res.append(cur)
for c in course[cur]:
indegree[c] -= 1 # 更新入度
if indegree[c] == 0:
queue.append(c)
if len(res) == numCourses:
return res
else:
return []
# 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: TreeNode) -> int:
# # 二分查找 找到最后一层节点个数
# # 树的深度
def getDepth(root):
if not root:
return 0
return getDepth(root.left) + 1
# def isExist(root, index, depth):
# while depth > 1:
# mid = (1 << (depth-1)) // 2
# if index < mid:
# root = root.left
# else:
# index -= mid
# root = root.right
# depth -= 1
# return root != None
# if not root:
# return 0
# depth = getDepth(root)
# count1 = (1 << (depth-1)) - 1
# # 二分查找最后一个节点索引
# start = 0
# end = count1
# while start <= end:
# mid = start + (end - start) // 2
# if isExist(root, mid, depth):
# start = mid + 1
# print(start)
# else:
# end = mid - 1
# return count1 + start
# 空树,节点数为 0
if root == None:
return 0
# 求左子树和右子树的深度
leftHeight = getDepth(root.left)
rightHeight = getDepth(root.right)
# 如果左子树的深度 = 右子树的深度,左子树为满二叉树
# 节点数 = 左子树的深度 + 右子树的深度 + 根节点
if leftHeight == rightHeight:
return (2 ** leftHeight - 1) + self.countNodes(root.right) + 1
# 如果左子树的深度 > 右子树的深度,右子树为满二叉树
# 节点数 = 左子树的深度 + 右子树的深度 + 根节点
else:
return (2 ** rightHeight - 1) + self.countNodes(root.left) + 1