代码随想录刷题Day22

7 阅读3分钟

找树左下角的值

层序遍历法

这道题用层序遍历还是挺好做的

# 层序遍历解法
from collections import deque
class Solution:
    def findBottomLeftValue(self, root: TreeNode | None) -> int:
        queue=deque()
        if root==None:
            return 
        queue.append(root)
        while queue:
            result=queue[0].val # 每遍历一层,都把最左侧的值更新一下
            for _ in range(len(queue)):
                node=queue.popleft()
                if node.left:
                    queue.append(node.left)
                if node.right:
                    queue.append(node.right)
        return result

递归法

class Solution:
    def findBottomLeftValue(self, root: TreeNode | None) -> int:
        max_depth=0
        result=None
        def traversal(node:TreeNode,depth:int):
            nonlocal max_depth
            nonlocal result
            if node.left is None and node.right is None:
                if depth>max_depth:
                    max_depth=depth
                    result=node.val
            if node.left:
                depth+=1
                traversal(node.left,depth)
                depth-=1
            if node.right:
                depth+=1
                traversal(node.right,depth)
                depth-=1
        traversal(root,1)
        return result

递归三部曲:

  1. 参数是节点和当前深度,无返回值
  2. 终止条件是叶子节点,且深度最大就记录结果
  3. 单层递归逻辑就是先递归左,再递归右,另外深度还有一个回溯的过程

我一开始是终止条件没想对,这个终止条件和二叉树的全部路径有点像,到了叶子节点就到了收获的时候了。这道题还额外要求了得是最大深度才行。

然后是单层递归逻辑,就是先递归左再递归右,有深度的记录,所以要回溯一下。

因为是先遍历左,再遍历右,所以如果同样是最大深度的一层,记录了左就不会记录右边了。

路径总和

# 错误解法
class Solution:
    def hasPathSum(self, root: TreeNode | None, targetSum: int) -> bool:
        if root is None:
            return False
        result=False
        def hasPS(node:TreeNode,_sum=0):
            nonlocal result
            if result is True:
                return
            _sum+=node.val
            if node.left is None and node.right is None:
                result= _sum==targetSum
                return
            if node.left:
                hasPS(node.left,_sum)
                _sum-=node.left.val # _sum不用手动回溯
            if node.right:
                hasPS(node.right,_sum)
                _sum-=node.right.val # 删掉
        hasPS(root)
        return result

这里我看代码随想录题型这道题有回溯,所以就在这加了回溯,但其实这里返回上一层的时候,这个_sum就自动恢复成上一层的_sum了,不用手动再减去下一层的值。

需不需要回溯,关键就是看回到上一层的时候,需要恢复的值有没有自动恢复,自动恢复了就不需要手动回溯了。

代码随想录里这道题的解法属于自己给自己找麻烦了

路径总和Ⅱ

class Solution:
    def pathSum(self, root: TreeNode | None, targetSum: int) -> list[list[int]]:
        result=[]
        if root is None:
            return result
        def findpath(node:TreeNode,path=None):
            nonlocal result
            if path is None:
                path=[]
            path.append(node.val)
            if node.left is None and node.right is None and sum(path)==targetSum:
                result.append(path[:]) #不能写path[]
            if node.left:
                findpath(node.left,path)
                path.pop()
            if node.right:
                findpath(node.right,path)
                path.pop()
        findpath(root)
        return result

这里就需要pop了,这属于是 python 的特性了。我的理解是:每一层递归里的 path 都是局部变量,但它们指向的是同一个列表对象。所以递归返回上一层的时候,列表不会自动回溯,需要手动回溯。保存结果的时候也需要写[:],否则指向的就是同一个列表对象,后续如果这个列表对象有改动,结果里也会跟着变动。

中序后序构造二叉树

这道题挺有意思的,自己想虽然想不到,但是背下来倒是很简单

class Solution:
    def buildTree(self, inorder: list[int], postorder: list[int]) -> TreeNode | None:
        if postorder==[]: #任意一个数组为空就返回
            return
        root_val=postorder[-1]
        root=TreeNode(root_val)

        inorder_root_index=inorder.index(root_val)
        
        inorder_left=inorder[:inorder_root_index]
        inorder_right=inorder[inorder_root_index+1:]

        postorder_left=postorder[:len(inorder_left)]
        postorder_right=postorder[len(inorder_left):-1]

        root.left=self.buildTree(inorder_left,postorder_left)
        root.right=self.buildTree(inorder_right,postorder_right)
        return root

这道题的逻辑大概是这样的:

  1. 后序数组的最后一位是根节点
  2. 根据根节点,到中序数组中划分出左子树元素和右子树元素
  3. 根据左子树的长度到后序数组中找出左子树,右子树
  4. 递归:输入左子树的中序和后序构造左子树最后把左子树的根节点返回给root,右子树同理

这道题要注意区间,保持区间不变性,保持左闭右开区间。

前序中序构造二叉树跟这道题思路差不多