257. 二叉树的所有路径
https://leetcode-cn.com/problems/binary-tree-paths/
难度简单416收藏分享切换为英文接收动态反馈
给定一个二叉树,返回所有从根节点到叶子节点的路径。
说明: 叶子节点是指没有子节点的节点。
示例:
输入:
1
/ \
2 3
\
5
输出: ["1->2->5", "1->3"]
解释: 所有根节点到叶子节点的路径为: 1->2->5, 1->3
文章目录
解法1 先序遍历
# -*- coding: utf-8 -*-
from typing import List, Optional
# 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: TreeNode) -> List[str]:
self.result = []
if not root:
return self.result
level = 0
cur_result = []
self._generate(root=root, level=level, cur_result=cur_result)
return self.result
def _generate(self, root: TreeNode, level, cur_result: List):
cur_result.append(str(root.val))
if root.left is None and root.right is None:
r = self._generate_path(cur_result)
self.result.append(r)
return
if root.left:
self._generate(root.left, level + 1, cur_result)
# reverse the current level
cur_result.pop(-1)
if root.right:
self._generate(root.right, level + 1, cur_result)
# reverse the current level
cur_result.pop(-1)
def _generate_path(self, result: List):
if not result:
return
return "->".join(result)
def create_tree(array: List, i: int, n: int) -> Optional[TreeNode]:
"""
:param array: 完全二叉树 对应的数组
:param i: 当前的索引
:param n: 数组的长度
:return:
"""
root = None
# terminator
if i >= n or i < 0 or array[i] is None:
return root
# current level logic
root = TreeNode(array[i])
# drill down 创建左右孩子的结点
root.left = create_tree(array, 2 * i + 1, n)
root.right = create_tree(array, 2 * i + 2, n)
return root
def preorder(root: TreeNode):
if not root:
return
print(f'{root.val}', end=' ')
preorder(root.left)
preorder(root.right)
if __name__ == '__main__':
array = [1, 2, 3, None, 5, None, None]
root = create_tree(array=array, i=0, n=len(array))
# preorder(root)
# print()
r = Solution().binaryTreePaths(root=root)
print(r)
pass
解法2 递归法
递归三部曲
第一确定递归条件, 找到递归条件后 收集结果 返回
第二 当前层 处理逻辑
第三 drill down 到下层
第四 reverse current level status
class Solution:
def binaryTreePaths(self, root: TreeNode) -> List[str]:
self.result = []
if not root:
return self.result
level = 0
cur_result = []
self._generate(root=root, level=level, cur_result=cur_result)
return self.result
def _generate(self, root: TreeNode, level, cur_result: List):
# terminator
if root.left is None and root.right is None:
cur_result.append(str(root.val))
r = self._generate_path(cur_result)
# print(r)
self.result.append(r)
return
# current logic
cur_result.append(str(root.val))
# drill down
if root.left:
self._generate(root.left, level + 1, cur_result)
# reverse the current level
cur_result.pop(-1)
if root.right:
self._generate(root.right, level + 1, cur_result)
# reverse the current level
cur_result.pop(-1)
def _generate_path(self, result: List):
if not result:
return
return "->".join(result)
解法2-1 递归
上面的递归中每次 保存一个结点, 之后 要回溯cur_result,这里换成一种方法,每次传入一个字符串,作为当前遍历的结果,每次递归的时候先把字符串生成好,由于Python中字符串是不可变的,所以每次进入递归的时
只是复制了一次,每层递归相互不影响,也就避免了回溯逻辑。即 reverse the current level 这样的逻辑。 同时 解法2中level并没有用到,因为到叶子结点的长度 我们无法提前知道,而我们的递归结束条件是判断当前结点的 左 右孩子是否为空。
# -*- coding: utf-8 -*-
from typing import List, Optional
# 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
def create_tree(array: List, i: int, n: int) -> Optional[TreeNode]:
"""
:param array: 完全二叉树 对应的数组
:param i: 当前的索引
:param n: 数组的长度
:return:
"""
root = None
# terminator
if i >= n or i < 0 or array[i] is None:
return root
# current level logic
root = TreeNode(array[i])
# drill down 创建左右孩子的结点
root.left = create_tree(array, 2 * i + 1, n)
root.right = create_tree(array, 2 * i + 2, n)
return root
def preorder(root: TreeNode):
if not root:
return
print(f'{root.val}', end=' ')
preorder(root.left)
preorder(root.right)
class Solution:
def binaryTreePaths(self, root: TreeNode) -> List[str]:
self.result = []
if not root:
return self.result
cur_result = ""
self._generate(root=root, cur_result=cur_result)
return self.result
def _generate(self, root: TreeNode, cur_result: str):
if not root:
return
if root.left is None and root.right is None:
cur_result += str(root.val)
self.result.append(cur_result)
return
cur_result = cur_result + str(root.val) + "->"
self._generate(root.left, cur_result)
self._generate(root.right, cur_result)
if __name__ == '__main__':
array = [1, 2, 3, None, 5, None, None]
root = create_tree(array=array, i=0, n=len(array))
r = Solution().binaryTreePaths(root=root)
print(r)
pass
解法2-2 递归解法
甚至可以这样写, 不需要直接进入 roo.left
,root.right
,如果没有就没有必要进入了,所以可以先判断一下,在进入递归。 同时递归终止条件 就不需要 判断 root 是否为空 这个判断,只要看 当前结点 左右孩子是否为空即可。
class Solution:
def binaryTreePaths(self, root: TreeNode) -> List[str]:
self.result = []
if not root:
return self.result
cur_result = ""
self._generate(root=root, cur_result=cur_result)
return self.result
def _generate(self, root: TreeNode, cur_result: str):
if root.left is None and root.right is None:
cur_result += str(root.val)
self.result.append(cur_result)
return
cur_result = cur_result + str(root.val) + "->"
if root.left:
self._generate(root.left, cur_result)
if root.right:
self._generate(root.right, cur_result)
解法3 广度优先搜索
广度优先搜索,只要遍历结点的时候每次 只保留当前路径结果,当遍历到叶子结点的时候,收集结果即可。
# -*- coding: utf-8 -*-
# Definition for a binary tree node.
from collections import deque
from typing import List, Optional
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
def create_tree(array: List, i: int, n: int) -> Optional[TreeNode]:
"""
:param array: 完全二叉树 对应的数组
:param i: 当前的索引
:param n: 数组的长度
:return:
"""
root = None
# terminator
if i >= n or i < 0 or array[i] is None:
return root
# current level logic
root = TreeNode(array[i])
# drill down 创建左右孩子的结点
root.left = create_tree(array, 2 * i + 1, n)
root.right = create_tree(array, 2 * i + 2, n)
return root
def preorder(root: TreeNode):
if not root:
return
print(f'{root.val}', end=' ')
preorder(root.left)
preorder(root.right)
class Solution:
def binaryTreePaths(self, root: TreeNode) -> List[str]:
self.result = []
if not root:
return self.result
que = deque()
# 入队列 当前结点 以及当前结点的 val
que.append(root)
que.append(str(root.val))
result = []
while que:
node = que.popleft()
path = que.popleft()
if node.left is None and node.right is None:
result.append(path)
if node.left:
que.append(node.left)
que.append(path + "->" + str(node.left.val))
if node.right:
que.append(node.right)
que.append(path + "->" + str(node.right.val))
return result
if __name__ == '__main__':
array = [1, 2, 3, None, 5, None, None]
root = create_tree(array=array, i=0, n=len(array))
# preorder(root)
# print()
r = Solution().binaryTreePaths(root=root)
print(r)
pass
Day 20220303 第二次总结 二叉树遍历
解法1 -递归
这里采用先序遍历法
# -*- coding: utf-8 -*-
from typing import List, Optional
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.all_result = []
cur_result = []
self._preorder(root, cur_result)
return self._build_path(self.all_result)
pass
@staticmethod
def _build_path(results: List) -> List:
new_result = []
for result in results:
item = '->'.join(result)
new_result.append(item)
return new_result
def _preorder(self, root: Optional[TreeNode], cur_result: List):
if not root:
return
# process current level
cur_result.append(str(root.val))
if root.left is None and root.right is None:
self.all_result.append(cur_result.copy())
return
if root.left:
# drill down
self._preorder(root.left, cur_result)
# reverse the current level status
cur_result.pop(-1)
if root.right:
# drill down
self._preorder(root.right, cur_result)
# reverse the current level status
cur_result.pop(-1)
解法2 递归的 迭代写法
使用栈 来模拟递归过程
# -*- coding: utf-8 -*-
from typing import List, Optional, Union
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]) -> Union[list[list], list[str]]:
all_result = []
if not root:
return all_result
stack = [(root, str(root.val))]
while stack:
node, cur_result = stack.pop()
cur_result: str
node: Optional[TreeNode]
# 到达叶子结点
if node.left is None and node.right is None:
all_result.append(cur_result)
if node.right:
stack.append((node.right, cur_result + '->' + str(node.right.val)))
if node.left:
stack.append((node.left, cur_result + '->' + str(node.left.val)))
return all_result
pass
解法3 广度优先搜索
这里使用bfs
搜索 遍历结点的时候,顺便 记录 遍历到当前结点的路径。
# -*- coding: utf-8 -*-
from collections import deque
from typing import List, Optional
from typing import Union
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
class Solution:
"""
广度优先搜索 BFS
"""
def binaryTreePaths(self, root: Optional[TreeNode]) -> Union[list[list], list[str]]:
all_result = []
if not root:
return all_result
que = deque()
que.append((root, str(root.val)))
while que:
node, cur_result = que.popleft()
# 到达叶子结点
if node.left is None and node.right is None:
all_result.append(cur_result)
if node.left:
que.append((node.left, cur_result + '->' + str(node.left.val)))
if node.right:
que.append((node.right, cur_result + '->' + str(node.right.val)))
return all_result