返回

动态规划的全新篇章:LeetCode 347 周赛 T4 深度解析

闲谈

利用动态规划和最长递增子序列,攻克 LeetCode 347 周赛 T4

简介

在 LeetCode 第 347 场单周赛中,T4 题考查了二维空间上的最长递增子序列问题。这道题要求从左上角单元格出发,只能向下或向右移动,找出经过单元格值构成的最长递增子序列。它融合了最长递增子序列 (LIS) 算法和动态规划思想,难度不容小觑。不过,掌握这两大算法的奥妙,就能将其巧妙结合,迎刃而解。

动态规划的魅力

动态规划是一种强大的算法思想,适用于解决复杂且重叠子问题的问题。它将大问题分解成若干小问题,逐个求解,最终得到大问题的解。

最长递增子序列的奥秘

最长递增子序列算法旨在求解给定序列中最长的递增子序列。递增子序列是指序列中的一组元素,其值严格递增。该算法的时间复杂度为 O(n^2),其中 n 为序列的长度。

巧妙结合,攻克难题

T4 题需要同时运用动态规划和最长递增子序列算法。我们把二维网格的每个单元格视为一个子问题,从左上角开始,使用动态规划逐个求解。求解每个子问题时,我们运用最长递增子序列算法,寻找从左上角单元格到当前单元格的最长递增子序列。

代码实现

def longest_increasing_subsequence(grid):
    # 创建备忘录,记录每个单元格的最长递增子序列长度
    memo = [[0] * len(grid[0]) for _ in range(len(grid))]
    # 初始化首行首列
    for i in range(len(grid)):
        memo[i][0] = 1
    for j in range(len(grid[0])):
        memo[0][j] = 1
    # 迭代网格,从第二行第二列开始
    for i in range(1, len(grid)):
        for j in range(1, len(grid[0])):
            # 计算当前单元格的最长递增子序列长度
            memo[i][j] = 1
            for x, y in [(i - 1, j), (i, j - 1)]:
                if grid[x][y] < grid[i][j]:
                    memo[i][j] = max(memo[i][j], memo[x][y] + 1)
    # 求备忘录中的最大值
    max_length = 0
    for i in range(len(grid)):
        for j in range(len(grid[0])):
            max_length = max(max_length, memo[i][j])
    return max_length

总结

LeetCode 347 周赛 T4 题考验了算法思维和代码实现能力。通过巧妙结合动态规划和最长递增子序列算法,我们可以有效解决这类问题。希望这篇文章能为你带来启发,助你攻克更多算法难题。

常见问题解答

1. 动态规划和最长递增子序列算法的本质区别是什么?
动态规划从整体到局部,解决重叠子问题,最终得到整体最优解。最长递增子序列算法从局部到整体,解决最长递增子序列问题。

2. 如何判断一个单元格是否属于当前的最长递增子序列?
如果该单元格的值大于其上一个单元格的值,则属于。

3. 为什么备忘录的初始化值是 1?
因为每个单元格都可以看作一个最长递增子序列,其长度为 1。

4. 求最长递增子序列的复杂度为何是 O(n^2)?
因为对于每个单元格,都要检查其上一个单元格的所有值是否满足递增条件。

5. 除了动态规划和最长递增子序列算法,还有哪些解决这类问题的算法?
贪心算法也可以解决最长递增子序列问题,但时间复杂度较高。