Leetcode 257 二叉树的所有路径
题目:
给你一个二叉树的根节点 root ,按 任意顺序 ,返回所有从根节点到叶子节点的路径。
叶子节点 是指没有子节点的节点。
示例 1:
输入:root = [1,2,3,null,5]
输出:[“1->2->5”,“1->3”]
示例 2:
输入:root = [1]
输出:[“1”]
提示:
- 树中节点的数目在范围 [1, 100] 内
- -100 <= Node.val <= 100
算法思想:
- 递归法:
递归参数:传入根节点,路径栈(保存的是根节点到当前叶子结点的节点值),结果列表
递归结束条件:如果当前节点的左右孩子节点都是None,说明访问到叶子结点,将当前结点到叶子节点的值按照特定的形式返回即可。
一次递归逻辑:递归左子树,递归右子树,记得每次获取当前路径后,将访问过的节点出栈,目的是继续从当前叶子结点的父节点继续访问其他孩子节点。 - 迭代法:采用类似先序遍历的方式,首先判断当前节点是否是叶子结点,如果是,说明访问到叶子结点,保存当前路径信息。如果不是,先遍历右孩子,在遍历左孩子,遍历的同时将当前节点的值加入到路径中并入path_st栈。
代码实现:
- 递归法
# Definition for a binary tree node.
class Solution:
def traversal(self, cur, path, result):
path.append(cur.val) # 中
if cur.left is None and cur.right is None: # 到达叶子节点
sPath = '->'.join(map(str, path))
result.append(sPath)
return
if cur.left: # 左
self.traversal(cur.left, path, result)
path.pop() # 回溯
if cur.right: # 右
self.traversal(cur.right, path, result)
path.pop() # 回溯
def binaryTreePaths(self, root):
result = []
path = []
if not root:
return result
self.traversal(root, path, result)
return result
import unittest
class TestSolution(unittest.TestCase):
def test_binaryTreePaths(self):
solution = Solution()
# Test case 1
root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
root.left.right = TreeNode(5)
expected_output = ["1->2->5", "1->3"]
self.assertEqual(solution.binaryTreePaths(root), expected_output)
if __name__ == '__main__':
unittest.main()
- 迭代法
class TreeNode:
def __init__(self, val=0, left=None, right=None) -> None:
self.val = val
self.left = left
self.right = right
def binaryTreePaths(self, root):
stack = []
if root is None: # 判断根节点是否为空,题目给出是不空
return stack
# 当前根节点和根节点的值都入栈,并把值转化为字符串
stack.append(root)
path_st = [str(root.val)]
result = []
while stack:
# 如果栈不空,出栈元素的同时,将path作为当前路径的其实路径
cur = stack.pop()
path = path_st.pop()
# 如果是根节点,将当前路径加入到result中
if cur.left is None and cur.right is None:
result.append(path)
# 如果右孩子不空,有孩子进栈,同时更新路径
if cur.right:
stack.append(cur.right)
path_st.append(path + '->' + str(cur.right.val))
# 左孩子同理,这里并不要求一定先是右孩子,然后是做孩子,实测发现颠倒过来一样适用,只不过换过来是先遍历右子树,在遍历左子树。
if cur.left:
stack.append(cur.left)
path_st.append(path + "->" + str(cur.left.val))
return result
Leetcode 404 左叶子之和
题目:
给定二叉树的根节点 root ,返回所有左叶子之和。
示例 1:
输入: root = [3,9,20,null,null,15,7]
输出: 24
解释: 在这个二叉树中,有两个左叶子,分别是 9 和 15,所以返回 24
示例 2:
输入: root = [1]
输出: 0
提示:
- 节点数在 [1, 1000] 范围内
- -1000 <= Node.val <= 1000
算法思想:
- 递归法:
递归参数:传入二叉树根节点
递归结束条件:当前节点是空节点,返回0;(可有可无:当前节点是叶子结点,返回0。这里可能很多人会有疑问,都是叶子节点了,为什么会返回0? 因为当前即使是叶子结点,无法确定是左叶子结点还是右叶子结点。那为什么可有可无? 如果没有这个条件,第一个条件也会return 0,无非就是多遍历一层。)
一次递归逻辑:递归遍历左子树,递归遍历右子树。要注意的是,递归遍历左子树的时候,我们要找的节点就在其中(为什么?左子树才有可能有左叶子。有人会说,右子树也有左叶子。这没问题,但站在当前这课独立右子树来说,依然是左子树才有可能有左叶子),也就是当前节点的左孩子节点不为None,并且左孩子是叶子结点。 - 迭代法:
类似于先序遍历或者后序遍历。这里要区分递归法。迭代法就是拿到节点就判断是否是符合条件的值。这一点于递归法不同。
代码实现:
- 递归法:
# 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 root is None:
return 0
if root.left is None and root.right is None: # 可有可无
return 0
leftValue = self.sumOfLeftLeaves(root.left) # 左
if root.left and not root.left.left and not root.left.right: # 左子树是左叶子的情况
leftValue = root.left.val
'''
为什么不能是先判断是不是if的条件,在进行递归?
第一:很容易将满足条件的值覆盖掉
第二:返回到上一层的时候在判断。也就是说如果当前节点的左孩子节点返回非0,那么这个if判断毫无意义;但如果当前节点的左孩子节点返回的是0,说明当前节点的左孩子就是要找的左节点。这里不是可有可无,是必须有
'''
rightValue = self.sumOfLeftLeaves(root.right) # 右
sum_val = leftValue + rightValue # 中
return sum_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 sumOfLeftLeaves(self, root: Optional[TreeNode]) -> int:
# 迭代法
if root is None:
return 0
stack = [root]
result = 0
while stack:
cur = stack.pop()
# if cur.left 与if cur.right先后顺序无所谓,无非就是先遍历哪边的子树
if cur.left:
stack.append(cur.left)
if cur.right:
stack.append(cur.right)
# 下边if判断放到if cur.left:之前也可以。这里的逻辑就是上来就判断是否是题目要求的值
if cur.left and cur.left.left is None and cur.left.right is None:
result += cur.left.val
return result