代码随想录算法训练营第十六天|LC513.找树坐下角的值|LC112.路径总和|LC113.路径总和Ⅱ|LC105.从前序与中序遍历序列构造二叉树|LC106.从中序与后序遍历序列构造二叉树

513. 找树左下角的值 - 力扣(LeetCode)

        要求:最后一行的最左边的值

from typing import List, Optional
from collections import deque
# 二叉树生成代码
def generate_tree(vals):
    if len(vals) == 0:
        return None
    que = [] # 定义队列
    fill_left = True # 由于无法通过是否为 None 来判断该节点的左子树是否可以填充,用一个记号判断是否需要填充左节点
    for val in vals:
        node = TreeNode(val) if val else None # 非空值返回节点类,否则返回 None
        if len(que)==0:
            root = node # 队列为空的话,用 root 记录根结点,用来返回
            que.append(node)
        elif fill_left:
            que[0].left = node
            fill_left = False # 填充过左子树后,改变记号状态
            if node: # 非 None 值才进入队列
                que.append(node)
        else:
            que[0].right = node
            if node:
                que.append(node)
            que.pop(0) # 填充完右子树,弹出节点
            fill_left = True #
    return root

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: Optional[TreeNode]) -> int:
        self.max_depth = float('-inf')
        self.res = None
        self.traversal(root, 0)
        return self.res

    def traversal(self, node, depth):
        if not node.left and not node.right:
            if depth > self.max_depth:
                self.max_depth = depth
                self.res = node.val
            return

        if node.left:
            depth += 1
            self.traversal(node.left, depth)
            # 减1是回溯,深度要减1
            depth -= 1
        if node.right:
            depth += 1
            self.traversal(node.right, depth)
            depth -= 1


if __name__ == '__main__':
    null = None
    root = [1,2,3,4,null,5,6,null,null,7]
    root = generate_tree(root)
    res = Solution().findBottomLeftValue(root)
    print(res)

112. 路径总和 - 力扣(LeetCode)

        使用递归+回溯,用回溯返回节点便于计算下一个节点的值;

from typing import List, Optional
from collections import deque
# 二叉树生成代码
def generate_tree(vals):
    if len(vals) == 0:
        return None
    que = [] # 定义队列
    fill_left = True # 由于无法通过是否为 None 来判断该节点的左子树是否可以填充,用一个记号判断是否需要填充左节点
    for val in vals:
        node = TreeNode(val) if val else None # 非空值返回节点类,否则返回 None
        if len(que)==0:
            root = node # 队列为空的话,用 root 记录根结点,用来返回
            que.append(node)
        elif fill_left:
            que[0].left = node
            fill_left = False # 填充过左子树后,改变记号状态
            if node: # 非 None 值才进入队列
                que.append(node)
        else:
            que[0].right = node
            if node:
                que.append(node)
            que.pop(0) # 填充完右子树,弹出节点
            fill_left = True #
    return root

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, cur:TreeNode, count:int):
        if not cur.left and not cur.right and count == 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: Optional[TreeNode], targetSum: int) -> bool:
        if root is None:
            return False
        return self.traversal(root, targetSum - root.val)

if __name__ == '__main__':
    null = None
    root = [5,4,8,11,null,13,4,7,2,null,null,null,1]
    targetSum = 22
    root = generate_tree(root)
    res = Solution().hasPathSum(root, targetSum)
    print(res)

113. 路径总和 II - 力扣(LeetCode)

        要遍历整个树,找到所有路径,所以递归函数不要返回值;

        LC112只需要找到是否存在即可,而LC113需要找到所有组合,故需要对所有路径进行遍历完全;

from typing import List, Optional
from collections import deque
# 二叉树生成代码
def generate_tree(vals):
    if len(vals) == 0:
        return None
    que = [] # 定义队列
    fill_left = True # 由于无法通过是否为 None 来判断该节点的左子树是否可以填充,用一个记号判断是否需要填充左节点
    for val in vals:
        node = TreeNode(val) if val else None # 非空值返回节点类,否则返回 None
        if len(que)==0:
            root = node # 队列为空的话,用 root 记录根结点,用来返回
            que.append(node)
        elif fill_left:
            que[0].left = node
            fill_left = False # 填充过左子树后,改变记号状态
            if node: # 非 None 值才进入队列
                que.append(node)
        else:
            que[0].right = node
            if node:
                que.append(node)
            que.pop(0) # 填充完右子树,弹出节点
            fill_left = True #
    return root

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right


class Solution:
    def __init__(self):
        self.res = []
        self.path = []

    def traversal(self, cur, count):
        # 遇到了叶子节点且找到了和为sum的路径
        if not cur.left and not cur.right and count == 0:
            self.res.append(self.path[:])
            return
        # 遇到叶子节点而没有找到合适的边,直接返回
        if not cur.left and not cur.right:
            return
        # 递归-左
        if cur.left:
            self.path.append(cur.left.val)
            count -= cur.left.val
            self.traversal(cur.left, count) # 递归
            count += cur.left.val # 回溯
            self.path.pop() # 回溯弹出

        # 递归-右
        if cur.right:
            self.path.append(cur.right.val)
            count -= cur.right.val
            self.traversal(cur.right, count) # 递归
            count += cur.right.val # 回溯
            self.path.pop() # 回溯弹出

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

if __name__ == '__main__':
    null = None
    root = [5,4,8,11,null,13,4,7,2,null,null,5,1]
    targetSum = 22
    root = generate_tree(root)
    res = Solution().pathSum(root, targetSum)
    print(res)

105. 从前序与中序遍历序列构造二叉树 - 力扣(LeetCode)

        有点难理解,下次来回头看

class Solution:
    def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:
        # 第一步: 特殊情况讨论: 树为空. 或者说是递归终止条件
        if not preorder:
            return None

        # 第二步: 前序遍历的第一个就是当前的中间节点.
        root_val = preorder[0]
        root = TreeNode(root_val)

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

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

        # 第五步: 切割preorder数组. 得到preorder数组的左,右半边.
        # ⭐️ 重点1: 中序数组大小一定跟前序数组大小是相同的.
        preorder_left = preorder[1:1 + len(inorder_left)]
        preorder_right = preorder[1 + len(inorder_left):]

        # 第六步: 递归
        root.left = self.buildTree(preorder_left, inorder_left)
        root.right = self.buildTree(preorder_right, inorder_right)
        # 第七步: 返回答案
        return root

106. 从中序与后序遍历序列构造二叉树 - 力扣(LeetCode)

        有点难理解,下次来回头看 

class Solution:
    def buildTree(self, inorder: List[int], postorder: List[int]) -> TreeNode:
        # 第一步: 特殊情况讨论: 树为空. (递归终止条件)
        if not postorder:
            return None

        # 第二步: 后序遍历的最后一个就是当前的中间节点.
        root_val = postorder[-1]
        root = TreeNode(root_val)

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

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

        # 第五步: 切割postorder数组. 得到postorder数组的左,右半边.
        # ⭐️ 重点1: 中序数组大小一定跟后序数组大小是相同的.
        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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值