返回

LeetCode周赛回顾:挑战图论压轴,难度不小

人工智能

LeetCode 周赛回顾:图论压轴题难倒众人,难度不小

上周末的 LeetCode 周赛难度不小,超出以往水平,令人大开眼界。本次周赛由理想汽车赞助,大奖只是理想汽车的周边,与豪气公司送 iWatch 的手笔相比,略显小气。

赛题回顾

本次周赛题目涵盖图论、字符串处理、动态规划等领域,其中图论压轴题更是难倒了众多参赛者。

第一题:检查每一行每一列都包含所有整数

这道题考察基础数组操作和集合应用。给定二维数组 grid,要求判断每一行和每一列是否都包含所有整数 [1, n]

解法:使用两个集合分别存储每一行和每一列的整数,遍历数组,将整数添加到对应集合。最后检查集合是否包含所有整数。

def checkValid(grid: List[List[int]]) -> bool:
    rows = len(grid)
    cols = len(grid[0])

    for i in range(rows):
        row_set = set()
        for j in range(cols):
            row_set.add(grid[i][j])
        if len(row_set) != rows:
            return False

    for j in range(cols):
        col_set = set()
        for i in range(rows):
            col_set.add(grid[i][j])
        if len(col_set) != cols:
            return False

    return True

第二题:找到字符串中指定单词的最短距离

这道题考察字符串处理中的滑动窗口算法。给定字符串 s 和单词 word,要求找到 words 中出现的所有位置,并返回这些位置之间的最短距离。

解法:使用两个指针 leftright 定义滑动窗口。移动指针,直到窗口包含 word。计算窗口长度,并与当前最短距离比较,更新最短距离。

def shortestDistance(s: str, word: str) -> int:
    left = 0
    right = 0
    min_distance = float('inf')
    word_len = len(word)

    while right < len(s):
        if s[right:right+word_len] == word:
            min_distance = min(min_distance, right - left + 1)
            left = right + 1
        right += 1

    return min_distance if min_distance != float('inf') else -1

第三题:删除石子使得石子堆不超过最大值

这道题考察动态规划中的背包问题。给定一堆石子,每个石子有一个重量。要求从石子堆中取出一些石子,使得剩下的石子堆重量不超过给定最大值。

解法:定义状态 dp[i][j],表示前 i 个石子中,取出的石子重量恰好为 j 的所有取法。使用递推关系计算 dp[i][j]。找到最小的 j,使得 dp[n][j] 不为 0。

def minStoneSum(piles: List[int], max_weight: int) -> int:
    n = len(piles)
    dp = [[0] * (max_weight + 1) for _ in range(n + 1)]

    for i in range(1, n + 1):
        for j in range(1, max_weight + 1):
            dp[i][j] = dp[i - 1][j]
            if piles[i - 1] <= j:
                dp[i][j] = max(dp[i][j], dp[i - 1][j - piles[i - 1]] + piles[i - 1])

    return dp[n][max_weight]

第四题:检查是否每一棵树都是另一个树的子树

这道题是本次周赛的压轴题,考察图论中的子树问题。给定两棵二叉树 rootsubRoot,要求判断 subRoot 是否为 root 的子树。

解法:递归比较 rootsubRoot 的根节点。如果根节点相等,递归比较 rootsubRoot 的左子树和右子树。如果在递归过程中,发现 subRoot 的某个子树与 root 的某个子树不相等,则 subRoot 不是 root 的子树。

def isSubtree(root: TreeNode, subRoot: TreeNode) -> bool:
    if not root:
        return False
    if not subRoot:
        return True
    if root.val == subRoot.val:
        if isSameTree(root, subRoot):
            return True
    return isSubtree(root.left, subRoot) or isSubtree(root.right, subRoot)

def isSameTree(root1: TreeNode, root2: TreeNode) -> bool:
    if not root1 and not root2:
        return True
    if not root1 or not root2:
        return False
    if root1.val != root2.val:
        return False
    return isSameTree(root1.left, root2.left) and isSameTree(root1.right, root2.right)

结论

本次 LeetCode 周赛的题目难度不小,图论压轴题更是难倒了众多参赛者。但是,通过认真分析题目,掌握算法知识,我们还是能够顺利解题的。希望大家能够通过本次周赛,对算法竞赛有更深入的了解,并不断提高自己的算法水平。

常见问题解答

  1. 本次周赛的难度如何?
    本次周赛的难度不小,特别是第四题图论压轴题,难倒了众多参赛者。

  2. 周赛题目覆盖了哪些算法领域?
    本次周赛题目涵盖了图论、字符串处理、动态规划等多个领域。

  3. 如何提高算法竞赛水平?
    可以通过认真分析题目,掌握算法知识,并多加练习来提高算法竞赛水平。

  4. 第四题的解法是否还有其他方法?
    第四题可以使用遍历 root 中所有子树,并与 subRoot 进行比较的方法解决,但这会比较低效。

  5. 如何判断两棵二叉树是否相同?
    可以通过递归比较两棵二叉树的根节点、左子树和右子树是否相等来判断两棵二叉树是否相同。