2024.3.(26,27号)力扣刷题记录-二叉树学习记录1

文章详细介绍了递归在解决二叉树问题中的应用,包括最大深度、最小深度、路径和、节点和等,涉及递归+非局部变量的方法,并提供了相关实例代码。同时提及了LeetCode中的题目作为参考。
摘要由CSDN通过智能技术生成

一、学习视频

【看到递归就晕?带你理解递归的本质!】 https://www.bilibili.com/video/BV1UD4y1Y769/?share_source=copy_web&vd_source=dc0e55cfae3b304619670a78444fd795

二、视频跟练代码

1.104. 二叉树的最大深度

方法均来自视频

(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 maxDepth(self, root: Optional[TreeNode]) -> int:
        #递归
        if root is None:    #None要使用is,不能使用==
            return 0
        ldepth = self.maxDepth(root.left)
        rdepth = self.maxDepth(root.right)
        return max(ldepth,rdepth) + 1   #加上当前节点

(2)递归+全局变量(准确来说是非局部)

关于nonlocal关键字的相关知识可见我的文章:http://t.csdnimg.cn/hfIpU

# 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 maxDepth(self, root: Optional[TreeNode]) -> int:
        #递归+全局变量(准确来说是非局部)
        ans = 0
        def f(node,cnt):
            if node is None:
                return
            cnt += 1
            nonlocal ans
            ans = max(ans,cnt)
            f(node.left,cnt)    #遍历左右子树
            f(node.right,cnt)
        f(root,0)
        return ans

时空复杂度均为O(n)。储存节点使用栈。

三、课后作业练习

1.111. 二叉树的最小深度

(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 minDepth(self, root: Optional[TreeNode]) -> int:
        #递归+非局部变量
        ans = 100000
        def f(node,cnt):
            nonlocal ans
            if node is None or cnt >= ans:
                #为空或大于等于最小深度时返回
                return
            cnt += 1
            if node.left is None and node.right is None:
                #在为叶子节点时更新并返回
                ans = min(ans,cnt)
                return
            f(node.left,cnt)
            f(node.right,cnt)
        f(root,0)
        return 0 if ans > 10000 else ans

(2)直接递归

# 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 minDepth(self, root: Optional[TreeNode]) -> int:
        #递归
        if root is None:
            return 0
        ldepth = self.minDepth(root.left)
        rdepth = self.minDepth(root.right)
        if ldepth == 0 or rdepth == 0:
            #为叶子节点返回1,0+1
            #不为叶子节点但一侧为空,返回不为空+1
            return max(ldepth,rdepth) + 1
        else:
            #两侧均不为空,返回小值+1
            return min(ldepth,rdepth) + 1

2.112. 路径总和

递归

# 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: Optional[TreeNode], targetSum: int) -> bool:
        #递归
        if root is None:
            return False
        if root.left is None and root.right is None:
            #叶子节点值是不是target
            #到达边界,开始归
            return root.val == targetSum
        #左右路径和是不是targetSum-root.val
        leftbool = self.hasPathSum(root.left,targetSum-root.val)
        rightbool = self.hasPathSum(root.right,targetSum-root.val)
        return leftbool or rightbool

3.113. 路径总和 II

递归

# 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 pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]:
        #递归
        if root is None:
            return []
        if root.left is None and root.right is None and root.val == targetSum:
            #表示这条路有一条可行路即为[root.val],如[[~],[~]]即为两条可行路
            return [[root.val]]     
        leftlst = self.pathSum(root.left,targetSum-root.val)
        rightlst = self.pathSum(root.right,targetSum-root.val)
        all_lst = leftlst + rightlst    #将左右可行路汇总
        for lst in all_lst:     #在可行路前加上当前节点,没可行路不参与循环
            lst.insert(0,root.val)
        return all_lst

4.129. 求根节点到叶节点数字之和

(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 sumNumbers(self, root: Optional[TreeNode]) -> int:
        # 递归,有根节点
        def f(node) -> List[str]:
            if node is None:
                return []
            if node.left is None and node.right is None:
                return [f'{node.val}']
            leftList = f(node.left)
            rightList = f(node.right)
            allList = leftList + rightList
            ans = []
            for s in allList:
                ans.append(f'{node.val}'+s)
            return ans
        strnums = f(root)
        s = 0
        for num in strnums:
            s += int(num)
        return s

(2)递归+数学 。方法来自题解(. - 力扣(LeetCode))。 

# 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 sumNumbers(self, root: Optional[TreeNode]) -> int:
        #递归+数学
        def f(node,temp) -> int:
            if node is None:
                return 0
            temp = 10 * temp + node.val     #在递的时候进行操作
            if node.left is None and node.right is None:
                return temp     #在叶子节点返回递的值
            l = f(node.left,temp)
            r = f(node.right,temp)
            return l+r
        return f(root,0)

 之前有一点这种想法,但是没有实现。只局限在了在归的时候进行操作,而没有想到在递的时候进行操作。

5.257. 二叉树的所有路径

递归

# 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 binaryTreePaths(self, root: Optional[TreeNode]) -> List[str]:
        #递归
        if root is None:
            return []
        if root.left is None and root.right is None:
            return [f"{root.val}"]  #只能从叶子节点开始记录
        leftStrList = self.binaryTreePaths(root.left)
        rightStrList = self.binaryTreePaths(root.right)
        all_StrList = leftStrList + rightStrList    #左右路径汇总
        ans = []
        for s in all_StrList:
            ans.append(f'{root.val}->' + s) #添加当前节点
        return ans

2024.3.27续:

6. 1448. 统计二叉树中好节点的数目

递归,在递的时候操作。没写出来,来自灵神题解(. - 力扣(LeetCode))。

# 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 goodNodes(self, root: TreeNode) -> int:
    # def goodNodes(self, root: TreeNode,mx = -inf) -> int:
        #递归
        def f(node,mx) -> int:
            if node is None:
                return 0
            left = f(node.left,max(mx,node.val))
            right = f(node.right,max(mx,node.val))
            return left + right + (mx <= node.val)
        return f(root,-inf)

7.987. 二叉树的垂序遍历

递归。不会,来自灵神题解(. - 力扣(LeetCode))。将几种写法都学习一下:

(1)dfs+哈希表

# 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 verticalTraversal(self, root: Optional[TreeNode]) -> List[List[int]]:
        # dfs+哈希表
        groups = defaultdict(list)
        def dfs(node: Optional[TreeNode], row:int, col: int):
            if node is None:
                return
            groups[col].append((row, node.val))
            dfs(node.left,row+1,col-1)
            dfs(node.right,row+1,col+1)
        dfs(root,0,0)

        ans = []
        for _,g in sorted(groups.items()):  # 按值对字典进行排序
            g.sort()    # 按照 row 排序,row 相同按照 val 排序
            ans.append([val for _,val in g])
        return ans

(2)dfs+哈希表+非局部变量

# 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 verticalTraversal(self, root: Optional[TreeNode]) -> List[List[int]]:
        # dfs+哈希表+非局部变量
        groups = defaultdict(list)
        min_col = 0
        def dfs(node: Optional[TreeNode], row:int, col: int):
            if node is None:
                return
            nonlocal min_col
            min_col = min(min_col,col)
            groups[col].append((row, node.val))
            dfs(node.left,row+1,col-1)
            dfs(node.right,row+1,col+1)
        dfs(root,0,0)

        ans = []
        for col in range(min_col,min_col+len(groups)):
            g = groups[col]
            g.sort()    # 按照 row 排序,row 相同按照 val 排序
            ans.append([val for _,val in g])
        return ans

(3)dfs+双列表。当时想使用列表存,但是既要在列表左端又要在右端存实现很麻烦,没有想到用双列表模拟双端列队。

# 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 verticalTraversal(self, root: Optional[TreeNode]) -> List[List[int]]:
        # dfs+双列表
        left,right = [],[]
        def dfs(node: Optional[TreeNode], row:int, col: int):
            if node is None:
                return
            if col < -len(left):
            # if col == -len(left)-1:
                left.append([])     #统计负数col
            elif col == len(right):
                right.append([])    #统计非负col
            (left[-col-1] if col < 0 else right[col]).append((row,node.val))
            dfs(node.left,row+1,col-1)
            dfs(node.right,row+1,col+1)
        dfs(root,0,0)

        ans = []
        for g in left[::-1] + right:
            g.sort()
            ans.append([val for _,val in g])    #只返回val列表
        return ans

(4) dfs+三元组存储。注意三元组col在row前,因为决定着排序是按照谁排。

# 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 verticalTraversal(self, root: Optional[TreeNode]) -> List[List[int]]:
        # dfs
        data = []
        def dfs(node: Optional[TreeNode], row:int, col: int):
            if node is None:
                return
            data.append((col,row,node.val))     #先col后row,排序顺序
            dfs(node.left,row+1,col-1)
            dfs(node.right,row+1,col+1)
        dfs(root,0,0)

        ans = []
        last_col = inf  #记录上一个列
        data.sort()
        for col, _, val in data:
            if col != last_col:
                last_col = col
                ans.append([])  #和上一个列不是同一个列就新加一个列表
            ans[-1].append(val)
        return ans

感谢你看到这里!一起加油吧!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值