代码随想录 day14:第六章 二叉树 part04

找树左下角的值

  • 本题递归偏难,反而迭代简单属于模板题, 两种方法掌握一下

在这里插入图片描述

  • 层序遍历
  • 如何判断是最后一行呢,其实就是深度最大的叶子节点一定是最后一行。
  • 如何找最左边的呢?可以使用前序遍历(当然中序,后序都可以,因为本题没有 中间节点的处理逻辑,只要左优先就行),保证优先左边搜索,然后记录深度最大的叶子节点,此时就是树的最后一行最左边的值。
if root is None:
            return 0
        queue = deque()
        queue.append(root)
        result = 0
        while queue:
            size = len(queue)
            for i in range(size):
                node = queue.popleft()
                if i == 0:
                    result = node.val
                if node.left:
                    queue.append(node.left)
                if node.right:
                    queue.append(node.right)
        return result

递归和回溯:

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

112. 路径总和

  • 涉及到回溯的过程,而且回溯的过程隐藏的还挺深
    1. 路径总和,和 113. 路径总和ii 一起做了。 优先掌握递归法。
      在这里插入图片描述
      思路:
  • 递归函数什么时候要有返回值,什么时候没有返回值,特别是有的时候递归函数返回类型为bool类型。这里总结如下三点:
    1. 如果需要搜索整棵二叉树且不用处理递归返回值,递归函数就不要返回值。(这种情况就是本文下半部分介绍的113.路径总和ii)
    1. 如果需要搜索整棵二叉树且需要处理递归返回值,递归函数就需要返回值。 (这种情况我们在236. 二叉树的最近公共祖先 (opens new window)中介绍)
    1. 如果要搜索其中一条符合条件的路径,那么递归一定需要返回值,因为遇到符合条件的路径了就要及时返回。(本题的情况)
     class Solution:
    def traversal(self, cur: TreeNode, count: int) -> bool:
        if not cur.left and not cur.right and count == 0: # 遇到叶子节点,并且计数为0
            return True
        if not cur.left and not cur.right: # 遇到叶子节点直接返回
            return False
        
        if cur.left: # 左
            count -= cur.left.val
            if self.traversal(cur.left, count): # 递归,处理节点
                return True
            count += cur.left.val # 回溯,撤销处理结果
            
        if cur.right: # 右
            count -= cur.right.val
            if self.traversal(cur.right, count): # 递归,处理节点
                return True
            count += cur.right.val # 回溯,撤销处理结果
            
        return False
    
    def hasPathSum(self, root: TreeNode, sum: int) -> bool:
        if root is None:
            return False
        return self.traversal(root, sum - root.val)    

113. 路径总和

在这里插入图片描述

class Solution:
    def traversal(self,cur,target,path,res):
        if not cur.left and not cur.right and target==0:
            res.append(path[:])
            return
        if not cur.left and not cur.right:
            return []
        if cur.left:
            path.append(cur.left.val)
            self.traversal(cur.left, target - cur.left.val, path, res)
            path.pop()
        
        if cur.right:
            path.append(cur.right.val)
            self.traversal(cur.right,target-cur.right.val,path,res)
            path.pop()

    def pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]:
        path=[]
        res=[]
        if not root:
            return res
        path.append(root.val)
        self.traversal(root,targetSum-root.val,path,res)
        return res

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

  • 106.从中序与后序遍历序列构造二叉树,105.从前序与中序遍历序列构造二叉树 一起做,思路一样的
    在这里插入图片描述
class Solution:
    def buildTree(self, inorder: List[int], postorder: List[int]) -> Optional[TreeNode]:
        # 中序遍历:左中右
        # 后序遍历:左右中

        # 第一步: 特殊情况讨论: 树为空. (递归终止条件)
        if not postorder:
            return None
        
        # 第二步: 后序遍历的最后一个就是当前的中间节点.
        root_val=postorder[-1]
        root=TreeNode(root_val)

        # 第三步: 找切割点.
        sep_idx=inorder.index(root_val)

        # 第四步: 切割inorder数组. 得到inorder数组的左,右半边.
        inorder_left=inorder[:sep_idx]
        inorder_right=inorder[sep_idx+1:]

        #第五步: 切割postorder数组. 得到postorder数组的左,右半边.
        postorder_left=postorder[:len(inorder_left)]
        postorder_right=postorder[len(inorder_left):len(postorder)-1]

        # 第六步: 递归
        root.left=self.buildTree(inorder_left,postorder_left)
        root.right=self.buildTree(inorder_right,postorder_right)

        return root

105.从前序与中序遍历序列构造二叉树

在这里插入图片描述

class Solution:
    def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
        # 前序遍历:中左右
        # 中序遍历:左中右

        if not preorder:
            return None
        root_val=preorder[0]#3
        root=TreeNode(root_val)#构建根节点
        # 切割点
        inorder_sep=inorder.index(root_val)#1
        #中序的左右数组
        inorder_left=inorder[:inorder_sep]#9
        inorder_right=inorder[inorder_sep+1:]#15,20,7
        #前序的左右数组
        preorder_left=preorder[1:len(inorder_left)+1]#9
        preorder_right=preorder[1+len(inorder_left):]#20,15,7
        # 迭代
        root.left=self.buildTree(preorder_left,inorder_left)
        root.right=self.buildTree(preorder_right,inorder_right)
        return root
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值