Leetcode 刷题第17天 | 513,112,106

Leetcode 513 查找树左下角的值

题目:

给定一个二叉树的 根节点 root,请找出该二叉树的 最底层 最左边 节点的值。
假设二叉树中至少有一个节点。
示例 1:
示例1
输入: root = [2,1,3]
输出: 1
示例 2:
示例2

输入: [1,2,3,4,null,5,6,null,null,7]
输出: 7
提示:

  • 二叉树的节点个数的范围是 [1, 1 0 4 10^4 104]
  • - 2 31 2^{31} 231 <= Node.val <= 2 31 2^{31} 231 - 1

算法思想:

误区:有可能会认为最左边的值来自于左子树,这样认为是错误的。也可能来源于右子树,只不过此时的右子树是最后一层从左到右的第一个节点。

  1. 递归法:
    递归参数:传入根节点,子函数传入当前节点的深度(最后一层的节点肯定是最深层的节点,所以要传入当前节点的深度)
    递归结束条件:(注意:当前寻找树左下角的值一定是遍历完整棵树,在遍历期间满足条件反复更新当前最左边的变量即可)如果当前节点是叶子结点,并且当前节点的深度大于之前遍历的所有节点的最大深度,更新结果于最大深度的值。
    一次递归逻辑:如果左子树不空,深度加1,同时左递归,递归结束返回上一层深度减一(回溯)。如果右子树不空,深度加1,递归结束返回上一层深度减一(回溯)
  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 findBottomLeftValue(self, root) -> int:
        if root is None:
            return 0    # 题目中给出的是最少一个节点
        self.result = None
        self.max_depth = float('-inf')
        self.traversal(root, 0)
        return self.result
    
    def travelsal(self, root, depth):
        # root 当前遍历的节点
        # 当前节点的深度 二叉树的根节点深度位0
        if root.left is None and root.right is None:
            if depth > self.max_depth:
                self.result = root.val
                self.max_depth = depth

        if root.left:
            depth = depth + 1
            self.travelsal(root.left)
            depth = depth - 1
        if root.right:
            depth = depth + 1
            self.travelsal(root.right)
            depth = depth - 1
  1. 迭代法:
# 定义TreeNode
class TreeNode:
    def __init__(self, val=0, left=None, right=None) -> None:
        self.val = val
        self.left = left
        self.right = right

import collections
class Solution:
    def findBottomLeftValue(self, root):
        if  root is None:
            return 0
        result = 0
        queue = collections.deque([root])
        while queue:
            for i in range(len(queue)):
                cur = queue.popleft()
                if i == 0:
                    result = cur.val
                if cur.left:
                    queue.append(cur.left)
                if cur.right:
                    queue.append(cur.right)
        return result

Leetcode 112 路径总和

题目:

给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false 。
叶子节点 是指没有子节点的节点。
示例 1:
示例1
输入:root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22
输出:true
解释:等于目标和的根节点到叶节点路径如上图所示。
示例 2:
示例2
输入:root = [1,2,3], targetSum = 5
输出:false
解释:树中存在两条根节点到叶子节点的路径:
(1 --> 2): 和为 3
(1 --> 3): 和为 4
不存在 sum = 5 的根节点到叶子节点的路径。
示例 3:
输入:root = [], targetSum = 0
输出:false
解释:由于树是空的,所以不存在根节点到叶子节点的路径。
提示:

  • 树中节点的数目在范围 [0, 5000] 内
  • -1000 <= Node.val <= 1000
  • -1000 <= targetSum <= 1000

算法思想:

  • 递归法:
    递归参数:传入根节点,targetNum
    递归结束条件:(注意:和上一道题一样,并不涉及“中”节点的逻辑处理,因此前中后序遍历都可以)当前节点的左右孩子节点都是空节点的时候,即当前节点是叶子结点且targetNum减到0 或者路径上的节点值的和为targetNum的时候返回True,否则当前节点是叶子结点且路径和不等于targetNum的时候返回False。
    一次递归逻辑:递归遍历左子树,同时剪枝操作(即如果当前节点接收到子节点的返回值为True,即返回True),否则继续遍历;递归遍历右子树,同时剪枝操作(类似左子树)
  • 迭代法:迭代法定义两个栈,第一个栈存当前遍历的节点;第二个栈存遍历到当前节点的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 traversal(self, root: TreeNode, count: int) -> bool:
        if root.left is None  and root.right is None and count == 0:
            return True
        if root.left is None and root.right is None and count != 0:
            return False
        
        if root.left:
            count -= root.left.val
            # 相当于剪枝的操作
            if self.traversal(root.left, count):
                return True
            count += root.left.val
        
        if root.right:
            count -= root.right.val
            # 相当于剪枝操作
            if self.traversal(root.right, count):
                return True
            count += root.right.val
        return False
    def hasPathSum(self, root, targetSum) -> bool:
        if root is None:
            return False
        return self.traversal(root, targetSum-root.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 hasPathSum(self, root, targetSum) -> bool:
        if root is None:
            return False
        st = [root]
        sum_st = [root.val]
        while st:
            cur = st.pop()
            num = sum_st.pop()
            if cur.left is None and cur.right is None and num == targetSum:
                return True
            
            if cur.left:
                st.append(cur.left)
                sum_st.append(num+cur.left.val)
            if cur.right:
                st.append(cur.right)
                sum_st.append(num+cur.right.val)
        return False

[Leetcode 106 从中序与后序遍历序列构造二叉树

](https://leetcode.cn/problems/construct-binary-tree-from-inorder-and-postorder-traversal/)

题目:

给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。
示例 1:
示例1
输入:inorder = [9,3,15,20,7], postorder = [9,15,7,20,3]
输出:[3,9,20,null,null,15,7]
示例 2:
输入:inorder = [-1], postorder = [-1]
输出:[-1]
提示:

  • 1 <= inorder.length <= 3000
  • postorder.length == inorder.length
  • -3000 <= inorder[i], postorder[i] <= 3000
  • inorder 和 postorder 都由 不同 的值组成
  • postorder 中每一个值都在 inorder 中
  • inorder 保证是树的中序遍历
  • postorder 保证是树的后序遍历

算法思想:

本题利用递归思想。主要分成六个步骤:
第一,判断后序遍历是否为空(题目中给出postorder和inorder符合后序和中序的条件,因此不用过多的条件判断),如果为空,直接返回None,返回值哪里接?接下来递归中接。
第二,后序遍历的最后一个节点就是当前二叉树的根节点
第三,从中序遍历中找到根节点的位置
第四,从中序遍历中切出左右子序列
第五,从后序遍历中切出左右子序列
第六,递归遍历左右子序列
第七,返回二叉树的根节点

代码实现:

# 定义二叉树
class TreeNode:
    def __init__(self, val=0, left=None, right=None) -> None:
        self.val = val
        self.left = left
        self.right = right

class Solution:
    def buildTree(self, inorder, postorder):
        # 第一步
        if len(postorder) == 0:
            return None
        #  第二步
        root_val = postorder[-1]
        root = TreeNode(root_val)

        # 第三步,寻找切割点
        separator_index = inorder.index(root_val)

        # 第四步,切割中序数组
        inorder_left = inorder[:separator_index]
        inorder_right = inorder[separator_index+1:]

        # 第五步,切割后序数组
        post_left = postorder[:len(inorder_left)]
        post_right = postorder[len(inorder_left):-1]

        # 第六步,递归
        root.left = self.buildTree(inorder_left, post_left)
        root.right = self.buildTree(inorder_right, post_right)

        # 第七步,返回root
        return root

import unittest

class TestSolution(unittest.TestCase):
    def test_buildTree(self):
        solution = Solution()

        # Test case 1
        inorder1 = [9, 3, 15, 20, 7]
        postorder1 = [9, 15, 7, 20, 3]
        result1 = solution.buildTree(inorder1, postorder1)
        self.assertEqual(result1.val, 3)
        self.assertEqual(result1.left.val, 9)
        self.assertEqual(result1.right.val, 20)
        self.assertEqual(result1.right.left.val, 15)
        self.assertEqual(result1.right.right.val, 7)

        # Test case 2
        inorder2 = [2, 1]
        postorder2 = [2, 1]
        result2 = solution.buildTree(inorder2, postorder2)
        self.assertEqual(result2.val, 1)
        self.assertEqual(result2.left.val, 2)

        # Test case 3
        inorder3 = [1, 2]
        postorder3 = [2, 1]
        result3 = solution.buildTree(inorder3, postorder3)
        self.assertEqual(result3.val, 1)
        self.assertEqual(result3.right.val, 2)

if __name__ == '__main__':
    unittest.main()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值