按照一位b站up主的刷题推荐顺序进行学习
每道题的题解代码有的参考他的题解或者leetcode评论区题解
class Solution:
def preorderTraversal(self, root: TreeNode) -> List[int]:
res = []
stack = []
while root or stack != []:
while root:
res.append(root.val)
stack.append(root)
root = root.left
cur = stack.pop(-1)
root = cur.right
return res
class Solution:
def inorderTraversal(self, root: TreeNode) -> List[int]:
ans = []
stack = []
while root or stack != []:
while root:
stack.append(root)
root = root.left
cur = stack.pop()
ans.append(cur.val)
root = cur.right
return ans
class Solution:
def postorderTraversal(self, root: TreeNode) -> List[int]:
res = []
stack = []
while root or stack != []:
while root:
res.append(root.val)
stack.append(root)
root = root.right
cur = stack.pop()
root = cur.left
return res[::-1]
class BSTIterator:
def __init__(self, root: TreeNode):
self.list = []
self.progress = 0
# 得到中序遍历结果
self.inOrder(root)
def inOrder(self, root):
stack = []
while root or stack != []:
while root:
stack.append(root)
root = root.left
cur = stack.pop(-1)
self.list.append(cur.val)
root = cur.right
def next(self) -> int:
res = self.list[self.progress]
self.progress += 1
return res
def hasNext(self) -> bool:
return self.progress != len(self.list)
class Solution:
def levelOrder(self, root: TreeNode) -> List[List[int]]:
if not root:
return []
queue = [root]
ans = []
while queue:
# 每次for循环遍历处理一层
# tmp_list用来临时存储下一层的节点
tmp_list = []
layer_num = len(queue)
for i in range(layer_num):
node = queue.pop(0)
# 把下一层节点从左到右加入队列
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
tmp_list.append(node.val)
ans.append(tmp_list)
return ans
class Solution:
def zigzagLevelOrder(self, root: TreeNode) -> List[List[int]]:
stack = []
def levelOrder(root, depth, stack):
if not root: return
if depth >= len(stack):
stack.append([])
stack[depth].append(root.val)
levelOrder(root.left, depth + 1, stack)
levelOrder(root.right, depth + 1, stack)
# 先层序遍历
levelOrder(root, 0, stack)
# 再根据层数逆序
for i in range(1, len(stack), 2):
stack[i] = stack[i][::-1]
return stack
class Solution:
def levelOrderBottom(self, root: TreeNode) -> List[List[int]]:
ans = []
def leverOrder(root, depth, stack):
if not root: return
if depth >= len(stack):
stack.append([])
stack[depth].append(root.val)
leverOrder(root.left, depth + 1, stack)
leverOrder(root.right, depth + 1, stack)
# 层序遍历逆序
leverOrder(root, 0, ans)
return ans[::-1]
class Solution:
def isValidBST(self, root: TreeNode) -> bool:
# 先序遍历二叉树,对每个节点判断是否符合取值范围
def check(root, l, r):
if not root:
return True
if root.val <= l or root.val >= r:
return False
# 限定左右节点的取值范围
return check(root.left, l, root.val) and check(root.right, root.val, r)
import math
return check(root, -math.inf, math.inf)
class Solution:
def recoverTree(self, root: TreeNode) -> None:
"""
Do not return anything, modify root in-place instead.
"""
# 中序遍历找到errorOne和errorTwo,交换
stack = []
pre = None
errOne = None
errTwo = None
while root or stack != []:
while root:
stack.append(root)
root = root.left
root = stack.pop()
# 定位errOne, errTwo
if pre and pre.val >= root.val:
if not errOne:
errOne = pre
errTwo = root
else:
errTwo = root
pre = root
root = root.right
# 交换errOne, errTwo
tmp = errOne.val
errOne.val = errTwo.val
errTwo.val = tmp
return root
class Solution:
def kthSmallest(self, root: TreeNode, k: int) -> int:
# 中序遍历到第k个值时返回
stack = []
n = 0
while root or stack != []:
while root:
stack.append(root)
root = root.left
cur = stack.pop()
n += 1
if n == k: return cur.val
root = cur.right
return
285/272锁住了
class Solution:
def binaryTreePaths(self, root: TreeNode) -> List[str]:
# 递归,根据每个节点的情况判断是否加入路径
if not root:
return []
if not root.left ans not root.right:
return [str(root.val)]
paths = []
if root.left:
for i in self.binaryTreePaths(root.left):
paths.append(str(root.val) + '->' + i)
if root.left:
for i in self.binaryTreePaths(root.right):
paths.append(str(root.val) + '->' + i)
return paths
270 锁了
class Solution:
def rightSideView(self, root: TreeNode) -> List[int]:
'''
# 取层序遍历中每一层的最后一个节点
stack = []
def levelOrder(root, depth, stack):
if not root: return
if depth >= len(stack):
stack.append([])
stack[depth].append(root.val)
levelOrder(root.left, depth + 1, stack)
levelOrder(root.right, depth + 1, stack)
levelOrder(root, 0, stack)
ans = []
for l in stack:
ans.append(l[-1])
return ans
'''
# 改进空间复杂度 层序遍历按照从右到左的顺序
ans = []
def dfs(root, depth):
if not root: return
if depth == len(ans):
ans.append(root.val)
dfs(root.right, depth + 1)
dfs(root.left, depth + 1)
dfs(root, 0)
return ans
class Solution:
def rob(self, nums: List[int]) -> int:
nums_len = len(nums)
if nums_len <= 1:
return 0 if nums_len == 0 else nums[0]
# dp[i] 代表截止到目前这一家,我们能够拿到的最大钱数
dp = [0] * nums_len
res = max(nums[0], nums[1])
for i in range(nums_len):
if i== 0:
dp[i] = nums[0]
elif i == 1:
dp[i] = max(nums[0], nums[1])
else:
dp[i] = max(dp[i-1], dp[i-2] + nums[i])
res = max(res, dp[i])
return res
class Solution:
def rob(self, nums: List[int]) -> int:
# 分类处理避免头尾成环的情况
nums_len = len(nums)
if nums_len <= 1:
return 0 if nums_len == 0 else nums[0]
nums1 = nums[:-1]
nums2 = nums[1:-1]
nums3 = nums[1:]
# 这里直接复用198的代码
return max(self.helper(nums1), self.helper(nums2), self.helper(nums3))
def helper(self, nums):
nums_len = len(nums)
if nums_len <= 1:
return 0 if nums_len == 0 else nums[0]
dp = [0] * nums_len
res = max(nums[0], nums[1])
for i in range(nums_len):
if i == 0:
dp[i] = nums[0]
elif i == 1:
dp[i] = max(nums[0], nums[1])
else:
dp[i] = max(dp[i-1], dp[i-2] + nums[i])
res = max(res, dp[i])
return res
class Solution:
def rob(self, root: TreeNode) -> int:
def dp(root):
if not root: return [0,0]
left = dp(root.left)
right = dp(root.right)
rob = root.val + left[1] + right[1]
not_rob = max(left[0], left[1]) + max(right[0], right[1])
return [rob, not_rob]
res = dp(root)
# 每个节点能够盗取的最大金额,分类为抢劫和不抢劫当前节点
# 0代表抢劫当前节点, 1代表不抢劫当前节点
return max(res[0], res[1])
255 锁了
class Solution:
def flatten(self, root: TreeNode) -> None:
"""
Do not return anything, modify root in-place instead.
"""
# 先序遍历
if not root:
return
# 先展平左节点,再展平右节点
left = self.flatten(root.left)
right = self.flatten(root.right)
# 再把左节点放到根节点的右边
root.left = None
root.right = left
# 再把原来的右节点放到现在的最右边
p = root
while p.right:
p = p.right
p.right = right
return root
156 锁了
class Solution:
def connect(self, root: 'Node') -> 'Node':
if not root:return
# 利用辅助函数,定义每两个相邻的节点需要完成的任务
def helper(node1, node2):
if not node1:
return
# 和自己相邻的节点连起来
node1.next = node2
# 递归自己的子节点
helper(node1.left, node1.right)
helper(node2.left, node2.right)
# 递归自己和相邻节点的子节点
helper(node1.right, node2.left)
helper(root.left, root.right)
return root
class Solution:
def connect(self, root: 'Node') -> 'Node':
# left_one代表左边第一个
left_one = root
# 逐层遍历
while left_one:
# 用head作为连接后的下一层的虚拟头节点
head = tail = Node(0)
# cur从这一层左边第一个开始
cur = left_one
while cur:
# 利用tail不断移动,连接这一层节点的下一层
if cur.left:
tail.next = cur.left
tail = tail.next
if cur.right:
tail.next = cur.right
tail = tail.next
cur = cur.next
left_one = head.next
return root
使用层序序列
class Codec:
def serialize(self, root):
"""Encodes a tree to a single string.
:type root: TreeNode
:rtype: str
"""
if not root: return ''
res = []
queue = [root]
while queue:
len_q = len(queue)
for i in range(len_q):
cur = queue.pop(0)
res.append('#' if not cur else str(cur.val))
if not cur: continue
queue.append(cur.left)
queue.append(cur.right)
return ','.join(res)
def deserialize(self, data):
"""Decodes your encoded data to tree.
:type data: str
:rtype: TreeNode
"""
if data == '': return
nodes = data.split(',')
root = TreeNode(int(nodes[0]))
queue = [root]
len_nodes = len(nodes)
i = 1
while i < len_nodes:
parent = queue.pop(0)
if nodes[i] != '#':
parent.left = TreeNode(int(nodes[i]))
queue.append(parent.left)
if nodes[i+1] != '#':
parent.right = TreeNode(nodes[i+1])
queue.append(parent.right)
i += 2
return root
和279一致即可
class Solution:
def generateTrees(self, n: int) -> List[TreeNode]:
# 将(1, i-1)看作左子树,(i+1, n)看作右子树
def helper(start, end):
res = []
if start > end:
res.append(None)
for i in range(start, end + 1):
leftChild = helper(start, i - 1)
rightChild = helper(i + 1, end)
# 排列组合
for left in leftChild:
for right in rightChild:
root = TreeNode(i)
root.left = left
root.right = right
res.append(root)
return res
if n == 0: return []
return helper(1, n)
class Solution:
def numTrees(self, n: int) -> int:
# 动态规划
# 假设1-n个节点中选择i节点作为根节点
# 则构成的二叉搜索树数量=以i节点左边的节点构成的二叉搜索树的数量*i节点右边的节点构成的二叉搜索树数量
# G[n]代表n个节点可以构成的二叉搜索树之和,
G = [0]*(n + 1)
G[0] = 1
G[1] = 1
for i in range(2, n+1):
for j in range(1, i+1):
G[i] += G[j - 1]*G[i - j]
return G[n]
class Solution:
def maxPathSum(self, root: TreeNode) -> int:
# 后序遍历找最大路径和
maxRes = - math.inf
def postOrder(root):
nonlocal maxRes
if not root:
return 0
left = max(0, postOrder(root.left))
right = max(0, postOrder(root.right))
maxRes = max(maxRes, root.val + left + right)
return root.val + max(left, right)
postOrder(root)
return maxRes
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
if p.val == q.val: return p
if p.val < root.val and q.val < root.val:
# 都在左边
return self.lowestCommonAncestor(root.left, p, q)
elif p.val > root.val and q.val > root.val:
# 都在右边
return self.lowestCommonAncestor(root.right, p, q)
else:
# 左右各一个
return root
思路:从根节点分别递归遍历自己的左右子树,有三种情况
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
# 如果已经遍历到底都找不到p或者q就返回None,如果已经遍历到p或者q,则返回这个
if not root or p == root or q == root: return root
# 假设p和q都在左子树,返回左子树中的公共节点(None或者找到了其中一个节点)
pqInleft = self.lowestCommonAncestor(root.left, p, q)
# 同理
pqInright = self.lowestCommonAncestor(root.right, p, q)
# 其中一个子树没找到,则结果一定在另外一个子树中
if not pqInleft:
return pqInright
elif not pqInright:
return pqInleft
# 左右子树都没找到,说明只有root=p=q
return root
250、333锁了
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
if p.val != q.val:
return False
left = self.isSameTree(p.left, q.left)
right = self.isSameTree(p.right, q.right)
return left and right
class Solution:
def maxDepth(self, root: TreeNode) -> int:
if not root:
return 0
return max(self.maxDepth(root.left), self.maxDepth(root.right)) + 1
class Solution:
def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:
if not preorder or not inorder:
return
# 1.从前序和中序中找到当前节点的值和左右子节点的前序和中序
# 当前节点的值=前序数组第一个
cur_value = preorder[0]
root = TreeNode(cur_value)
# 找到当前节点的值在中序数组中的位置,前面的就是左节点的中序数组,后面的就是右节点的中序数组
i = 0
while cur_value != inorder[i]:
i += 1
inorder_mid = i
# 根据左节点的前序数组长度等于左节点的中序数组长度找到左右节点的前序数组
# 2.建立左右子节点
root.left = self.buildTree(preorder[1:inorder_mid+1], inorder[:inorder_mid])
root.right = self.buildTree(preorder[inorder_mid+1:], inorder[inorder_mid+1:])
return root
class Solution:
def buildTree(self, inorder: List[int], postorder: List[int]) -> TreeNode:
if not inorder or not postorder:
return
# 1.根据中序和后序找到左右子树的中序和后序
# 后序的最后一个元素代表当前节点的值
cur_value = postorder[-1]
root = TreeNode(cur_value)
# 找到当前值在中序数组的位置
i = 0
while cur_value != inorder[i]:
i += 1
inorder_mid = i
# 2.建立左右子树
root.left = self.buildTree(inorder[:inorder_mid], postorder[:inorder_mid])
root.right = self.buildTree(inorder[inorder_mid+1:], postorder[inorder_mid:-1])
return root
class Solution:
def sortedArrayToBST(self, nums: List[int]) -> TreeNode:
if not nums: return
nums_len = len(nums)
mid = nums_len//2
root = TreeNode(nums[mid])
root.left = self.sortedArrayToBST(nums[: mid])
root.right = self.sortedArrayToBST(nums[mid + 1:])
return root
class Solution:
def sortedListToBST(self, head: ListNode) -> TreeNode:
if not head: return
elif not head.next: return TreeNode(head.val)
# 用快慢指针找到中点
slow = head
mid = slow.next
fast = mid.next
while fast and fast.next:
slow = slow.next
mid = slow.next
fast = fast.next.next
slow.next = None
root = TreeNode(mid.val)
root.left = self.sortedListToBST(head)
root.right = self.sortedListToBST(mid.next)
return root
class Solution:
def isBalanced(self, root: TreeNode) -> bool:
if not root: return True
def dfs(root):
if not root: return 0
return max(dfs(root.left), dfs(root.right)) + 1
left = dfs(root.left)
right = dfs(root.right)
if abs(left - right) > 1:
return False
return self.isBalanced(root.left) and self.isBalanced(root.right)
class Solution:
def minDepth(self, root: TreeNode) -> int:
if not root:
return 0
# 排除非叶子节点的路径
if not root.left and not root.right:
return 1
if not root.left:
return 1 + self.minDepth(root.right)
elif not root.right:
return 1 + self.minDepth(root.left)
else:
return min(self.minDepth(root.left), self.minDepth(root.right)) + 1
class Solution:
def hasPathSum(self, root: TreeNode, targetSum: int) -> bool:
if not root: return False
# 排除只是根节点的路径
if root.val == targetSum and not root.left and not root.right:
return True
targetSum = targetSum - root.val
return self.hasPathSum(root.left, targetSum) or self.hasPathSum(root.right, targetSum)
class Solution:
def pathSum(self, root: TreeNode, targetSum: int) -> List[List[int]]:
ans = []
def helper(root, sum, res):
nonlocal ans
if not root: return
sum -= root.val
if sum == 0 and not root.left and not root.right:
ans.append(res + [root.val])
helper(root.left, sum, res+[root.val])
helper(root.right, sum, res+[root.val])
helper(root, targetSum, [])
return ans
class Solution:
def sumNumbers(self, root: TreeNode) -> int:
res = []
def dfs(root, tmp):
nonlocal res
if not root:return
if not root.left and not root.right:
res.append(tmp + str(root.val))
return
dfs(root.left, tmp + str(root.val))
dfs(root.right, tmp + str(root.val))
dfs(root, '')
ans = 0
for arr in res:
ans += int(arr)
return ans
class Solution:
def countNodes(self, root: TreeNode) -> int:
if not root: return 0
def getDepth(root):
return 1 + getDepth(root.left) if root else -1
res = 0
h = getDepth(root)
while root:
if getDepth(root.right) == h - 1:
# 如果右子树的高度等于h-1,则说明左子树是完全二叉树
# 加上左子树的节点
res += 1 << h
# 遍历右子树
root = root.right
else:
# 如果右子树的高度小于h-1,说明此时右子树一定是一个完全二叉树
# 加上右子树的节点
res += 1 << (h - 1)
# 接着遍历左子树
root = root.left
h -= 1
return res
class Solution:
def invertTree(self, root: TreeNode) -> TreeNode:
if not root:
return
# 后续遍历翻转左右节点
self.invertTree(root.left)
self.invertTree(root.right)
tmp = root.left
root.left = root.right
root.right = tmp
return root
298、366锁了
class Solution:
def isSymmetric(self, root: TreeNode) -> bool:
if not root: return False
def helper(left, right):
if not left and not right:
return True
if not left or not right or left.val != right.val:
return False
return helper(left.left, right.right) and helper(left.right, right.left)
return helper(root.left, root.right)