144. 二叉树的前序遍历
难度:☆2
a. 递归法
嵌套函数或成员函数来实现递归。LC94/144/145 是初学者学习递归最好的例子,牢记递归三要素:确定递归函数的参数和返回值,确定终止条件,确定单层递归的逻辑。
# 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]:
ans = []
self.preTraversal(root, ans)
return ans
def preTraversal(self, node, ans):
if not node:
return
ans.append(node.val)
self.preTraversal(node.left, ans)
self.preTraversal(node.right, ans)
b. 迭代法(栈模拟递归)
用栈来模拟递归(递归就是用栈实现的)。根节点入栈,只要栈不空,循环取栈顶节点出栈。若节点存在,则将它的值加入结果数组中。将它的右、左孩子入栈,这样出栈的顺序就是左、右。若节点不存在,continue进入下一次循环。最后返回结果数组。
class Solution:
def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
ans = list()
stack = [root]
while stack:
node = stack.pop()
if node:
ans.append(node.val)
stack.append(node.right)
stack.append(node.left)
else:
continue
return ans
另一种实现是节点的值加入结果数组后,分别判断右、左孩子是否存在,存在则入栈。
class Solution:
def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
# 根节点为空则返回空列表
if not root:
return []
stack = [root]
result = []
while stack:
node = stack.pop()
# 中节点先处理
result.append(node.val)
# 右孩子先入栈
if node.right:
stack.append(node.right)
# 左孩子后入栈
if node.left:
stack.append(node.left)
return result
c. 迭代法的前中后序遍历统一写法
【思维难度较大】,注意中间节点的处理:放回栈,再让一个None进栈。参考LC94。
class Solution:
def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
result = list()
stack = list()
if root:
stack.append(root)
while stack:
node = stack.pop()
if node:
if node.right: # 右
stack.append(node.right)
if node.left: # 左
stack.append(node.left)
stack.append(node) # 中
stack.append(None)
else:
node = stack.pop()
result.append(node.val)
return result
145. 二叉树的后序遍历
难度:☆2
a. 递归法
嵌套函数或成员函数来实现递归。LC94/144/145 是初学者学习递归最好的例子,牢记递归三要素:确定递归函数的参数和返回值,确定终止条件,确定单层递归的逻辑。
class Solution:
def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
ans = []
self.postTraversal(root, ans)
return ans
def postTraversal(self, node, ans):
if not node:
return
self.postTraversal(node.left, ans)
self.postTraversal(node.right, ans)
ans.append(node.val)
b. 迭代法(栈模拟递归)
参考LC144,稍作修改:先处理左孩子,再处理右孩子,最后返回的结果数组要翻转一下。
class Solution:
def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
ans = list()
stack = [root]
while stack:
node = stack.pop()
if node is None:
continue
else:
ans.append(node.val)
stack.append(node.left)
stack.append(node.right)
return ans[::-1]
class Solution:
def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
if not root:
return []
stack = [root]
result = []
while stack:
node = stack.pop()
# 中节点先处理
result.append(node.val)
# 左孩子先入栈
if node.left:
stack.append(node.left)
# 右孩子后入栈
if node.right:
stack.append(node.right)
# 将最终的数组翻转
return result[::-1]
c. 迭代法的前中后序遍历统一写法
【思维难度较大】,注意中间节点的处理:放回栈,再让一个None进栈。参考LC94。
class Solution:
def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
result = list()
stack = list()
if root:
stack.append(root)
while stack:
node = stack.pop()
if node:
stack.append(node) # 中
stack.append(None)
if node.right: # 右
stack.append(node.right)
if node.left: # 左
stack.append(node.left)
else:
node = stack.pop()
result.append(node.val)
return result
94. 二叉树的中序遍历
难度:☆2
a. 递归法
嵌套函数或成员函数来实现递归。LC94/144/145 是初学者学习递归最好的例子,牢记递归三要素:确定递归函数的参数和返回值,确定终止条件,确定单层递归的逻辑。
class Solution:
def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
ans = []
self.inTraversal(root, ans)
return ans
def inTraversal(self, node, ans):
if not node:
return
self.inTraversal(node.left, ans)
ans.append(node.val)
self.inTraversal(node.right, ans)
b. 迭代法(栈模拟递归)
需要一个指针指向当前节点,并用栈来保存一路向左的每一个节点。只要碰到没有左孩子的节点,弹出栈顶节点,把它的值加入结果数组,指针指向右孩子。循环条件是or。
class Solution:
def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
result = list()
stack = list()
cur = root
while cur or stack:
if cur:
stack.append(cur)
cur = cur.left
else:
cur = stack.pop()
result.append(cur.val)
cur = cur.right
return result
另一种迭代法没有指针,但是修改root会降低代码可读性。
class Solution:
def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
result = list()
stack = list()
while root or stack:
while root:
stack.append(root)
root = root.left
root = stack.pop()
result.append(root.val)
root = root.right
return result
c. 迭代法的前中后序遍历统一写法
【思维难度较大】,注意中间节点的处理:放回栈,再让一个None进栈。
在中序遍历问题中,无法同时解决访问节点(遍历节点)和处理节点(将元素放进结果集)不一致的情况。我们就将访问的节点放入栈中,把要处理的节点也放入栈中但是要做标记。标记就是将处理的节点放入栈之后,紧接着放入一个空指针作为标记。 这种方法也可以叫做标记法。
class Solution:
def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
result = list()
stack = list()
if root:
stack.append(root)
while stack:
node = stack.pop()
if node:
if node.right: # 右
stack.append(node.right)
stack.append(node) # 中
stack.append(None)
if node.left: # 左
stack.append(node.left)
else:
node = stack.pop()
result.append(node.val)
return result