Leetcode 刷题第16天 |257,404

Leetcode 257 二叉树的所有路径

题目:

给你一个二叉树的根节点 root ,按 任意顺序 ,返回所有从根节点到叶子节点的路径。
叶子节点 是指没有子节点的节点。
示例 1:
示例1
输入:root = [1,2,3,null,5]
输出:[“1->2->5”,“1->3”]
示例 2:
输入:root = [1]
输出:[“1”]
提示:

  • 树中节点的数目在范围 [1, 100] 内
  • -100 <= Node.val <= 100

算法思想:

  1. 递归法:
    递归参数:传入根节点,路径栈(保存的是根节点到当前叶子结点的节点值),结果列表
    递归结束条件:如果当前节点的左右孩子节点都是None,说明访问到叶子结点,将当前结点到叶子节点的值按照特定的形式返回即可。
    一次递归逻辑:递归左子树,递归右子树,记得每次获取当前路径后,将访问过的节点出栈,目的是继续从当前叶子结点的父节点继续访问其他孩子节点。
  2. 迭代法:采用类似先序遍历的方式,首先判断当前节点是否是叶子结点,如果是,说明访问到叶子结点,保存当前路径信息。如果不是,先遍历右孩子,在遍历左孩子,遍历的同时将当前节点的值加入到路径中并入path_st栈。

代码实现:

  1. 递归法
# 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()
  1. 迭代法
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:
示例1
输入: root = [3,9,20,null,null,15,7]
输出: 24
解释: 在这个二叉树中,有两个左叶子,分别是 9 和 15,所以返回 24
示例 2:
输入: root = [1]
输出: 0
提示:

  • 节点数在 [1, 1000] 范围内
  • -1000 <= Node.val <= 1000

算法思想:

  1. 递归法:
    递归参数:传入二叉树根节点
    递归结束条件:当前节点是空节点,返回0;(可有可无:当前节点是叶子结点,返回0。这里可能很多人会有疑问,都是叶子节点了,为什么会返回0? 因为当前即使是叶子结点,无法确定是左叶子结点还是右叶子结点。那为什么可有可无? 如果没有这个条件,第一个条件也会return 0,无非就是多遍历一层。)
    一次递归逻辑:递归遍历左子树,递归遍历右子树。要注意的是,递归遍历左子树的时候,我们要找的节点就在其中(为什么?左子树才有可能有左叶子。有人会说,右子树也有左叶子。这没问题,但站在当前这课独立右子树来说,依然是左子树才有可能有左叶子),也就是当前节点的左孩子节点不为None,并且左孩子是叶子结点。
  2. 迭代法:
    类似于先序遍历或者后序遍历。这里要区分递归法。迭代法就是拿到节点就判断是否是符合条件的值。这一点于递归法不同。

代码实现:

  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 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
  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 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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值