Bootstrap

Datawhale组队学习笔记task2——leetcode面试题

写在前面

教程内容来自Datawhale
开源教程:https://github.com/datawhalechina/leetcode-notes/blob/main/docs/ch07/index.md
在线学习网站:https://www.datawhale.cn/learn/summary/67
ε=(´ο`*)))唉感觉自己是个笨小孩儿,还在

Day5题目

1.0112.路径总和

在这里插入图片描述

解答

思路:DFS深度优先搜索遍历,一直向下找到叶子节点(需要同时判断节点的左右子树同时为空),如果到叶子节点时sum==0,说明找到了一条符合要求的路径。

# 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 not root:return False
        if not root.left and not root.right:
            return targetSum == root.val
        return self.hasPathSum(root.left,targetSum - root.val) or self.hasPathSum(root.right,targetSum - root.val)

时间复杂度:O(n)
空间复杂度:O(1)
题解:
回溯:利用DFS找到从根节点到叶子节点的所有路径,只要有任何一条路径的和等于sum,就返回true。
(并非严格意义上的回溯法,因为没有重复利用path变量)

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    def hasPathSum(self, root, sum):
        if not root: return False
        res = []
        return self.dfs(root, sum, res, [root.val])
        
    def dfs(self, root, target, res, path):
        if not root: return False
        if sum(path) == target and not root.left and not root.right:
            return True
        left_flag, right_flag = False, False
        if root.left:
            left_flag = self.dfs(root.left, target, res, path + [root.left.val])
        if root.right:
            right_flag = self.dfs(root.right, target, res, path + [root.right.val])
        return left_flag or right_flag

时间复杂度:O(n)
空间复杂度:O(1)
BFS:使用队列保存遍历到每个节点时的路径和,如果该节点恰好是叶子节点,并且路径和正好等于sum,说明找到了解。

# 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 not root:
            return False
        que = collections.deque()
        que.append((root,root.val))
        while que:
            node,path = que.popleft()
            if not node.left and not node.right and path == targetSum:
                return True
            if node.left:
                que.append((node.left,path + node.left.val))
            if node.right:
                que.append((node.right,path + node.right.val))
        return False

时间复杂度:O(n)
空间复杂度:O(n)

2.0113路径总和II

在这里插入图片描述

解答

题解:
典型的回溯问题,解法包含先序遍历+路径记录两部分:

  • 先序遍历:按照“根、左、右”的顺序,遍历树的所有节点。
  • 路径记录:在先序遍历中,记录从根节点到当前节点的路径。当路径满足 (1) 根节点到叶节点形成的路径 且 (2) 各节点值的和等于目标值 targetSum 时,将此路径加入结果列表。
    在这里插入图片描述
    算法流程:
    函数pathSum(root,targetSum):
    初始化:结果列表res,路径列表path
    返回值:返回res即可
    函数recur(root,tar):
    递推参数:当前节点root,当前目标值tar。
    终止条件:若节点root为空,则直接返回
    递推工作:
    1.路径更新:将当前节点值root.val加入路径path
    2.目标值更新:tar = tar - root.val(即目标值tar从targetSum减至0)
    3.路径记录:当(1)root为叶节点且(2)路径和等于目标值,则将此路径path加入res
    4.先序遍历:递归左/右子节点
    5.路径恢复:向上回溯前,需要将当前节点从路径path中删除,即执行path.pop()
# 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]]:
        res,path = [],[]
        def recur(root,tar):
            if not root:return
            path.append(root.val)
            tar -= root.val
            if tar == 0 and not root.left and not root.right:
                res.append(list(path))
            recur(root.left,tar)
            recur(root.right,tar)
            path.pop()

        recur(root,targetSum)
        return res

时间复杂度:O(n)
空间复杂度:O(n)

3.0101.对称二叉树

在这里插入图片描述

解答

题解:
对称二叉树定义: 对于树中 任意两个对称节点 L 和 R ,一定有:
L.val = R.val :即此两对称节点值相等。
L.left.val = R.right.val :即 L 的 左子节点 和 R 的 右子节点 对称。
L.right.val = R.left.val :即 L 的 右子节点 和 R 的 左子节点 对称。
根据以上规律,考虑从顶至低递归,判断每对左右节点是否对称,从而判断树是否为对称二叉树。
在这里插入图片描述

# 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 isSymmetric(self, root: Optional[TreeNode]) -> bool:
        def recur(L,R):
            if not L and not R:return True
            if not L or not R or L.val != R.val:return False
            return recur(L.left,R.right) and recur(L.right,R.left)
        return not root or recur(root.left,root.right)

时间复杂度:O(N)
空间复杂度:O(N)

Day6题目

1.0124.二叉树中的最大路径和

在这里插入图片描述

解答

# 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 maxPathSum(self, root: Optional[TreeNode]) -> int:
        ans = -inf
        def dfs(node:Optional[TreeNode]) -> int:
            if node is None:
                return 0 #没有节点,和为0
            l_val = dfs(node.left) #左子树最大链和
            r_val = dfs(node.right) #右子树最大链和
            nonlocal ans
            ans = max(ans,l_val + r_val + node.val) #两条链拼成路径
            return max(max(l_val,r_val) + node.val,0) #当前子树最大链和(注意这里和0取最大值)
        dfs(root)
        return ans

时间复杂度:O(n)
空间复杂度:O(n)

2.0199.二叉树的右视图

在这里插入图片描述

解答

思考:即找每一层最右边的节点,可以利用层次遍历。
流程:
1、初始化队列,先将二叉树的根结点放入队列;根据队列是否为空作为循环条件;
2、获取当前层的元素个数(队列长度),并将队列尾部的元素值添加到右视图中。
3、按照队列长度遍历队列中的元素,并将其左右孩子(如果存在)添加到队列尾部,然后将当前元素出队。
4、重复步骤2,3,直到队列为空。

# 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 rightSideView(self, root: Optional[TreeNode]) -> List[int]:
        if not root:return []
        q = deque([root])
        ans = []
        while q:
            nxt = deque()
            size = len(q)
            ans.append(q[-1].val)
            for _ in range(size):
                cur = q.popleft()
                if cur.left:
                    nxt.append(cur.left)
                if cur.right:
                    nxt.append(cur.right)
            q = nxt
        return ans

时间复杂度:O(n)
空间复杂度:O(n)

3.0226.翻转二叉树

在这里插入图片描述

解答

思考:递归
根据二叉树镜像的定义,考虑递归遍历(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 invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        if not root:return
        tmp = root.left
        root.left = self.invertTree(root.right)
        root.right = self.invertTree(tmp)
        return root

时间复杂度 O(N) : 其中 N 为二叉树的节点数量,建立二叉树镜像需要遍历树的所有节点,占用 O(N) 时间。
空间复杂度 O(N) : 最差情况下(当二叉树退化为链表),递归时系统需使用 O(N) 大小的栈空间。

Day7题目

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

在这里插入图片描述

解答

2.0098.验证二叉搜索树

在这里插入图片描述

解答

3.0110.平衡二叉树

在这里插入图片描述

解答

Day8题目

1.0200.岛屿数量

在这里插入图片描述

解答

2.0695.导语的最大面积

在这里插入图片描述

解答

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

在这里插入图片描述

解答

;