【leetcode刷刷】513.找树左下角的值、112. 路径总和 113.路径总和ii、106.从中序与后序遍历序列构造二叉树 、105.从前序与中序遍历序列构造二叉树

513. 找树左下角的值

  1. 这题最先想的就是层次遍历法很简单,只需要输出最后一行的第一个就行
  2. 硬用递归的话,就想到,如果按照一个顺序递归的话,似乎可以做到先左后右,这样的话只在深度增长的时候覆盖一次result,就不会在右边节点的时候进行覆盖操作。
  3. 但其实递归的前序后序还是有点懵,因此一开始写出来的是找树右下角的值。
  4. 但实际上depth_left>=depth_right这句,加上等于就是找左边,不加=就是找右边?
class Solution:
    def traversal(self, root):
        if root is None:
            return 0, root
        if not root.left and not root.right:
            return 1, root.val
        depth_left, left_node_left = self.traversal(root.left)
        depth_right, left_ndoe_right = self.traversal(root.right)
        if depth_left >= depth_right:
            return depth_left + 1, left_node_left
        else: return depth_right + 1, left_ndoe_right

    def findBottomLeftValue(self, root: Optional[TreeNode]) -> int:
        # 递归,返回结果?
        # 返回深度?如果按先左后右的覆盖顺序,是不是第一个出现的就是最左
        depth, left_node = self.traversal(root)
        return left_node


        # 层次遍历
        q = collections.deque()
        q.append(root)
        while(q):
            res = []
            for i in range(len(q)):
                node = q.popleft()
                res.append(node.val)
                if node.left:
                    q.append(node.left)
                if node.right:
                    q.append(node.right)
        return res[0]

题解里的递归:

  1. 又加上了回溯?回溯是因为有一个参数需要传入递归的函数,但是本身这个函数在运行的时候不希望这个参数是变化的?但是这里的情况,如果不递归有影响吗?
  2. 这里是depth > self.max_depth的时候,对result进行覆盖。而不是我之前写的left>=right。因此这里就存在前序的问题,前序和后序的结果应该是不一样的。
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. 自己写的递推,这次输出是结果,参数是target和sum。当叶子节点的时候输出sum的结果。
class Solution:
    def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
        return self.traversal(root, targetSum, 0)

    def traversal(self, root, target, sum_):
        if not root:
            return False
        sum_ += root.val  # 这里加上了,后面是不是要回溯啊
        if not root.left and not root.right:   # 叶子节点就进行处理
            if sum_ == target:
                return True
            else:
                return False
        left = self.traversal(root.left, target, sum_)
        right = self.traversal(root.right, target, sum_)
        sum_ -= root.val   # 回溯?
        return left or right
        
  1. 看了题解之后,感觉可以只改target,不用传sum这个参数。这样的话递归的时候传入target-root.val,相当于隐形递归
class Solution:
    def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
        return self.traversal(root, targetSum)

    def traversal(self, root, target):
        if not root:
            return False
        # sum_ += root.val  # 这里加上了,后面是不是要回溯啊
        if not root.left and not root.right:   # 叶子节点就进行处理
            if root.val == target:
                return True
            else:
                return False
        left = self.traversal(root.left, target-root.val)
        right = self.traversal(root.right, target-root.val)
        # sum_ -= root.val   # 回溯?
        return left or right

113. 路径总和ii

  1. 但我试了一下,在if里回溯,和在if外回溯,好像都一样。但是当left和right都有的时候,不就相当于是一个回溯一步和两步吗,是不一样的吧。所以回溯到底是啥???搞不懂。
class Solution:
    def pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]:
        path_res = []
        self.path_sum(root, targetSum, [], path_res)
        return path_res

    def path_sum(self, root, target, path, path_res):
        if not root:
            return 
        path.append(root.val)
        if not root.left and not root.right and root.val == target:
            print(path)
            path_res.append(list(path))
        if root.left:
            self.path_sum(root.left, target-root.val, path, path_res)
            path.pop()
        if root.right:
            self.path_sum(root.right, target-root.val, path, path_res)
            path.pop()
        

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

  1. 蛮好想的递归,一次就ac了。所以下一题没写。
class Solution:
    def buildTree(self, inorder: List[int], postorder: List[int]) -> Optional[TreeNode]:
        # 感觉可以递归
        n = len(postorder)
        if n == 0:
            return 
        if n == 1:
            return TreeNode(inorder[0])

        mid = postorder[n-1]
        # 找切割点.
        i = inorder.index(mid)
        mid_node = TreeNode(mid)
        
        left = self.buildTree(inorder[0:i], postorder[0:i])
        right = self.buildTree(inorder[i+1:], postorder[i:n-1])
        mid_node.left = left
        mid_node.right = right
        return mid_node

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

你可能感兴趣的:(leetcode,算法,数据结构)