前中后序遍历问题
分解思路、遍历思路双解法题目
LeetCode104题 二叉树的最大深度
分解思路-递归法,自底向上收集最大深度,后序位置操作,递归函数有返回值
# 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
left = self.maxDepth(root.left)
right = self.maxDepth(root.right)
return 1 + max(left, 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:
self.res = 0
self.traversal(root, 1)
return self.res
def traversal(self, root, depth):
if not root:
return
self.res = max(self.res, depth)
self.traversal(root.left, depth + 1)
self.traversal(root.right, depth + 1)
LeetCode111题 二叉树的最小深度
分解思路-递归解法
# 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 minDepth(self, root: Optional[TreeNode]) -> int:
if not root:
return 0
elif not root.left and not root.right:
return 1
if root.left and root.right:
left = self.minDepth(root.left)
right = self.minDepth(root.right)
elif root.left:
left = self.minDepth(root.left)
right = float('inf')
elif root.right:
left = float('inf')
right = self.minDepth(root.right)
return 1 + min(left, 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 minDepth(self, root: Optional[TreeNode]) -> int:
if not root:
return 0
self.res = float('inf')
self.traversal(root, 1)
return self.res
def traversal(self, root, depth):
if not root:
return
if not root.left and not root.right:
self.res = min(self.res, depth)
self.traversal(root.left, depth + 1)
self.traversal(root.right, depth + 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 minDepth(self, root: Optional[TreeNode]) -> int:
from collections import deque
res = 0
if root is None:
return res
queue = deque([root])
while queue:
res += 1
num = len(queue)
for i in range(num):
node = queue.popleft()
# 层序遍历,可以提前停止搜索
if node.left is None and node.right is None:
return res
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
return res
LeetCode226题 翻转二叉树
分解思路-递归法,自底向上翻转,后序位置操作
# 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 invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
if not root:
return
left = self.invertTree(root.left)
right = self.invertTree(root.right)
root.left = right
root.right = 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 invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
def traversal(node):
if node is None or (node.left is None and node.right is None):
return
tmp = node.left
node.left = node.right
node.right = tmp
traversal(node.left)
traversal(node.right)
traversal(root)
return root
分解思路解法题目
LeetCode222题 完全二叉树的节点个数
由于完全二叉树的性质,其子树一定有一棵是满的,只消耗 O(logn) 的复杂度而不会继续递归,所以时间复杂度为O(logn) * O(logn)
# 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: Optional[TreeNode]) -> int:
if root is None:
return 0
r = self.getDepth(root)
if r > 0:
return 2**r - 1
else:
return 1 + self.countNodes(root.left) + self.countNodes(root.right)
def getDepth(self, node):
left_depth = 1
left_node = node.left
right_depth = 1
right_node = node.right
while left_node:
left_depth += 1
left_node = left_node.left
while right_node:
right_depth += 1
right_node = right_node.right
if left_depth == right_depth:
return left_depth
else:
return -1
LeetCode110题 平衡二叉树
分解思路-递归法
# 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 isBalanced(self, root: Optional[TreeNode]) -> bool:
r = self.getHeight(root)
if r == -1:
return False
else:
return True
def getHeight(self, node):
if node is None:
return 0
left_height = self.getHeight(node.left)
if left_height == -1:
return -1
right_height = self.getHeight(node.right)
if right_height == -1:
return -1
if abs(left_height - right_height) > 1:
return -1
return 1 + max(left_height, right_height)
LeetCode404题 左叶子之和
分解思路-递归法
# 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 sumOfLeftLeaves(self, root: Optional[TreeNode]) -> int:
if not root:
return 0
res = 0
if root.left and not root.left.left and not root.left.right:
res += root.left.val
res += self.sumOfLeftLeaves(root.left) + self.sumOfLeftLeaves(root.right)
return res
LeetCode112题 路径总和
# 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 root is None:
return False
if root.left is None and root.right is None:
if targetSum - root.val == 0:
return True
else:
return False
return self.hasPathSum(root.left, targetSum - root.val) or self.hasPathSum(root.right, targetSum - root.val)
遍历思路解法题目
LeetCode114题 二叉树展开为链表
遍历思路-迭代法
# 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 flatten(self, root: Optional[TreeNode]) -> None:
"""
Do not return anything, modify root in-place instead.
"""
if not root:
return
dummy = TreeNode()
cur = dummy
stack = [root]
while stack:
node = stack.pop()
if node.right:
stack.append(node.right)
node.right = None
if node.left:
stack.append(node.left)
node.left = None
cur.right = node
cur = node
dummy.right = None
LeetCode257题 二叉树的所有路径
遍历思路-递归法,涉及到回溯
# 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 binaryTreePaths(self, root: Optional[TreeNode]) -> List[str]:
self.res = []
self.traversal(root, str(root.val))
return self.res
def traversal(self, root, path):
if root.left is None and root.right is None:
self.res.append(path)
return
if root.left:
self.traversal(root.left, path + '->' + str(root.left.val))
if root.right:
self.traversal(root.right, path + '->' + str(root.right.val))
LeetCode513题 找树左下角的值
遍历思路-递归法,涉及到回溯
# 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 findBottomLeftValue(self, root: Optional[TreeNode]) -> int:
self.max_depth = float('-inf')
self.res = None
self.traversal(root, 1)
return self.res
def traversal(self, root, depth):
if not root.left and not root.right:
if depth > self.max_depth:
self.max_depth = depth
self.res = root.val
return
if root.left:
self.traversal(root.left, depth + 1)
if root.right:
self.traversal(root.right, depth + 1)
LeetCode113题 路径总和II
# 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]]:
self.res = []
if root is None:
return self.res
self.traversal(root, targetSum, [])
return self.res
def traversal(self, node, target, tmp_res):
if node.left is None and node.right is None:
if target - node.val == 0:
self.res.append(tmp_res + [node.val])
return
if node.left:
self.traversal(node.left, target - node.val, tmp_res + [node.val])
if node.right:
self.traversal(node.right, target - node.val, tmp_res + [node.val])
同时遍历两个树问题
LeetCode100题 相同的树
两个树是相同的树=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 isSameTree(self, p: Optional[TreeNode], q: Optional[TreeNode]) -> bool:
if p is None and q is None:
return True
elif (p is not None and q is None) or (p is None and q is not None):
return False
elif p.val != q.val:
return False
left = self.isSameTree(p.left, q.left)
right = self.isSameTree(p.right, q.right)
return left and right
LeetCode101题 对称二叉树
在递归遍历的过程中,要同时遍历左右两个子树,比较的是两个子树的里侧和外侧的元素是否相等,同时我们在后序位置,自底向上收集比较结果
分解思路-递归法:
# 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:
return self.is_sym(root.left, root.right)
def is_sym(self, left, right):
if (left is None and right is not None) or (left is not None and right is None):
return False
elif left is None and right is None:
return True
elif left.val != right.val:
return False
o = self.is_sym(left.left, right.right)
i = self.is_sym(left.right, right.left)
return o and i
子树匹配问题-与KMP算法的结合
LeetCode572题 另一棵树的子树
两个子树相同,可以推出它们的深度优先搜索队列相同,但如果两个子树的深度优先搜索队列相同,它们不一定是相同的子树。比如假设s由两个点组成,1是根,2是1的左孩子;t也由两个点组成,1是根,2是1的右孩子,这样一来s和t的深度优先搜索序列相同,但s和t并不相同。
为了解决这个问题,我们可以引入特殊值填充深度优先搜索队列,当一个节点的左孩子或者右孩子为空的时候,就插入这个特殊值,这样深度优先搜索序列就唯一对应一棵树。
处理完之后,就可以通过KMP算法解题,将复杂度降为O(n)。
# 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 isSubtree(self, root: Optional[TreeNode], subRoot: Optional[TreeNode]) -> bool:
next_node_list, next_list = self.getNext(subRoot)
stack = [root]
j = 0
while stack:
node = stack.pop()
node_val = node.val if node else 10001
while j > 0 and next_node_list[j] != node_val:
j = next_list[j - 1]
if next_node_list[j] == node_val:
j += 1
if j == len(next_list):
return True
if node:
stack.append(node.right)
stack.append(node.left)
return False
def getNext(self, subRoot):
next_node_list = [subRoot.val]
next_list = [0]
j = 0
stack = [subRoot.right, subRoot.left]
while stack:
node = stack.pop()
node_val = node.val if node else 10001
while j > 0 and next_node_list[j] != node_val:
j = next_list[j - 1]
if next_node_list[j] == node_val:
j += 1
next_node_list.append(node_val)
next_list.append(j)
if node:
stack.append(node.right)
stack.append(node.left)
return next_node_list, next_list
层序遍历问题
LeetCode116题 填充每个节点的下一个右侧节点指针
层次遍历
"""
# 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]':
from collections import deque
if root is None:
return
queue = deque([root])
while queue:
num = len(queue)
for i in range(num):
node = queue.popleft()
if i < num - 1:
node.next = queue[0]
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
return root