LeetCode-1463. 摘樱桃 II【数组 动态规划 矩阵】

LeetCode-1463. 摘樱桃 II【数组 动态规划 矩阵】

题目描述:

给你一个 rows x cols 的矩阵 grid 来表示一块樱桃地。 grid 中每个格子的数字表示你能获得的樱桃数目。

你有两个机器人帮你收集樱桃,机器人 1 从左上角格子 (0,0) 出发,机器人 2 从右上角格子 (0, cols-1) 出发。

请你按照如下规则,返回两个机器人能收集的最多樱桃数目:

从格子 (i,j) 出发,机器人可以移动到格子 (i+1, j-1),(i+1, j) 或者 (i+1, j+1) 。

当一个机器人经过某个格子时,它会把该格子内所有的樱桃都摘走,然后这个位置会变成空格子,即没有樱桃的格子。

当两个机器人同时到达同一个格子时,它们中只有一个可以摘到樱桃。

两个机器人在任意时刻都不能移动到 grid 外面。

两个机器人最后都要到达 grid 最底下一行。

示例 1:

输入:grid = [[3,1,1],[2,5,1],[1,5,5],[2,1,1]]

输出:24

解释:机器人 1 和机器人 2 的路径在上图中分别用绿色和蓝色表示。

机器人 1 摘的樱桃数目为 (3 + 2 + 5 + 2) = 12 。

机器人 2 摘的樱桃数目为 (1 + 5 + 5 + 1) = 12 。

樱桃总数为: 12 + 12 = 24 。

示例 2:

输入:grid = [[1,0,0,0,0,0,1],[2,0,0,0,0,3,0],[2,0,9,0,0,0,0],[0,3,0,5,4,0,0],[1,0,2,3,0,0,6]]

输出:28

解释:机器人 1 和机器人 2 的路径在上图中分别用绿色和蓝色表示。

机器人 1 摘的樱桃数目为 (1 + 9 + 5 + 2) = 17 。

机器人 2 摘的樱桃数目为 (1 + 3 + 4 + 3) = 11 。

樱桃总数为: 17 + 11 = 28 。

示例 3:

输入:grid = [[1,0,0,3],[0,0,0,3],[0,0,3,3],[9,0,3,3]]

输出:22

示例 4:

输入:grid = [[1,1],[1,1]]

输出:4

提示:

rows == grid.length

cols == grid[i].length

2 <= rows, cols <= 70

0 <= grid[i][j] <= 100

解题思路一:动态规划一般有自顶向下和自底向上两种编写方式,其中自顶向下也被称为「记忆化搜索」。

@lru_cache(None) 是 Python 中 functools 模块中的一个装饰器,它提供了一种缓存函数调用结果的机制。在该代码中,@lru_cache(None) 被应用在 dfs 函数上,意味着使用了一个无大小限制的缓存来存储函数调用的结果。这里有几点解释:

LRU Cache 的意义:LRU (Least Recently Used) 是一种缓存替换策略,即最近最少使用。当缓存满了的时候,LRU 算法会淘汰最近最少使用的项,以腾出空间来存储新的项。这种机制在动态规划中很有用,因为它可以避免重复计算。

@lru_cache(None) 的作用:@lru_cache(None) 将函数的结果缓存起来,以便在后续相同参数的调用时能够直接返回缓存中的结果,而不必重新计算。参数 None 表示使用无大小限制的缓存,这意味着所有的调用结果都会被缓存下来,直到程序结束或者手动清除缓存为止。

节省计算时间:在动态规划中,往往会有很多重复的子问题。使用缓存可以避免重复计算这些子问题,从而显著提高程序的运行效率。在该代码中,使用 @lru_cache(None) 可以避免在同一位置和状态下重复计算最大值。

总之,@lru_cache(None) 的作用是通过缓存函数调用的结果来避免重复计算,从而提高程序的运行效率,特别是在动态规划等需要大量重复计算的场景下非常有用。

python 复制代码
class Solution:
    def cherryPickup(self, grid: List[List[int]]) -> int:
        m, n = len(grid), len(grid[0])
        
        def getValue(i, j1, j2):
            return grid[i][j1] + grid[i][j2] if j1 != j2 else grid[i][j1]

        @lru_cache(None)
        def dfs(i, j1, j2):
            if i == m - 1:
                return getValue(i, j1, j2)
            
            best = 0
            for dj1 in [j1 - 1, j1, j1 + 1]:
                for dj2 in [j2 - 1, j2, j2 + 1]:
                    if 0 <= dj1 < n and 0 <= dj2 < n:
                        best = max(best, dfs(i + 1, dj1, dj2))
            return best + getValue(i, j1, j2)

        return dfs(0, 0, n-1)

时间复杂度:O(mn2)

空间复杂度:O(mn2)

解题思路二:0

python 复制代码

时间复杂度:O(n)

空间复杂度:O(n)

解题思路三:0

python 复制代码

时间复杂度:O(n)

空间复杂度:O(n)


创作不易,观众老爷们请留步... 动起可爱的小手,点个赞再走呗 (๑◕ܫ←๑) 欢迎大家关注笔者,你的关注是我持续更博的最大动力

原创文章,转载告知,盗版必究




♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠

相关推荐
俺不要写代码几秒前
lambda表达式理解
c++·算法
澈2074 分钟前
动态内存管理:从基础到实战详解
c++·算法
想唱rap9 分钟前
C++11之包装器
服务器·开发语言·c++·算法·ubuntu
im_AMBER20 分钟前
Leetcode 158 数组中的第K个最大元素 | 查找和最小的 K 对数字
javascript·数据结构·算法·leetcode·
脱氧核糖核酸__24 分钟前
LeetCode热题100——48.旋转图像(题解+答案+要点)
c++·算法·leetcode
木井巳27 分钟前
【递归算法】字母大小写全排列
java·算法·leetcode·决策树·深度优先
宵时待雨28 分钟前
优选算法专题2:滑动窗口
数据结构·c++·笔记·算法
Mr_pyx29 分钟前
LeetCode HOT 100 —— 矩阵置零(多种解法详解)
算法·leetcode·矩阵
葫三生30 分钟前
《论三生原理》系列:文化自信、知识范式重构与科技自主创新的思想运动源头?
大数据·人工智能·科技·深度学习·算法·重构·transformer
Q741_14733 分钟前
每日一题 力扣 3761. 镜像对之间最小绝对距离 哈希表 数组 C++ 题解
c++·算法·leetcode·哈希算法·散列表