zoukankan      html  css  js  c++  java
  • 剑指 Offer 47. 礼物的最大价值(动态规划dp)

    • 题目描述
    在一个 m*n 的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于 0)。你可以从棋盘的左上角开始拿格子里的礼物,并每次向右或者向下移动一格、直到到达棋盘的右下角。给定一个棋盘及其上面的礼物的价值,请计算你最多能拿到多少价值的礼物?
    
     
    
    示例 1:
    
    输入: 
    [
      [1,3,1],
      [1,5,1],
      [4,2,1]
    ]
    输出: 12
    解释: 路径 1→3→5→2→1 可以拿到最多价值的礼物

    这道题,第一想法就是用动态规划,也找到了转移方程,但是呢,就是实现的过程有问题,来我们看看题解大佬的清晰分析。

    • 解法:动态规划

    1.为什么想到用动态规划?

    从棋盘的左上角开始拿格子里的礼物,并每次 向右 或者 向下 移动一格、直到到达棋盘的右下角。根据题目说明,易得某单元格只可能从上边单元格或左边单元格到达。

     这一步是可以得到的,OK?

    看,这是不是就是个动态规划典型情况?动态规划是把一个大问题拆解成一堆小问题,并且将一个问题拆成几个子问题,分别求解这些子问题,即可推断出大问题的解。

    2.动态规划具有以下性质:

    • 【无后效性】“未来与过去无关”,这就是无后效性。
    • 【最优子结构】大问题的最优解可以由小问题的最优解推出,这个性质叫做“最优子结构性质”

    我们可以定义状态dp,dp(i,j)代表从棋盘左上角开始,到达单元格(i,j)时能拿到礼物的最大累计价值。主要方法是每次通过改变grid单元格元素的值,将grid矩阵当作dp矩阵。(这里参考大佬的题解)

     代码

    class Solution:
        def maxValue(self, grid: List[List[int]]) -> int:
            if not grid:
                return 0
            for i in range(len(grid)):
                for j in range(len(grid[0])):
                    if i ==0 and j == 0:
                        continue
                    if i == 0:
                        grid[i][j] += grid[i][j-1]
                    elif j ==0:
                        grid[i][j] += grid[i-1][j]
                    else:
                        grid[i][j] += max(grid[i][j-1], grid[i-1][j])
            return grid[-1][-1]

    时间复杂度O(MN):分别为两个for循环遍历的矩阵长宽

    空间复杂度O(1):原地修改grid大小不用额外空间

    • 优化

    优化的目的是当grid很大,i=0或者j=0的情况仅仅占少数,相当于循环每轮都冗余了一次判断。因此,可先初始化矩阵第一行和第一列,再开始遍历递推。

    class Solution:
        def maxValue(self, grid: List[List[int]]) -> int:
            if not grid:
                return 0
            m, n = len(grid), len(grid[0])
            for j in range(1, n): #初始化第一行
                grid[0][j] += grid[0][j-1]
            for i in range(1, m): #初始化第一列
                grid[i][0] += grid[i-1][0]
    
            for i in range(1, len(grid)):
                for j in range(1, len(grid[0])):
                        grid[i][j] += max(grid[i][j-1], grid[i-1][j])
            return grid[-1][-1]

    参考:https://leetcode-cn.com/problems/li-wu-de-zui-da-jie-zhi-lcof/solution/mian-shi-ti-47-li-wu-de-zui-da-jie-zhi-dong-tai-gu/

  • 相关阅读:
    LeetCode OJ 112. Path Sum
    LeetCode OJ 226. Invert Binary Tree
    LeetCode OJ 100. Same Tree
    LeetCode OJ 104. Maximum Depth of Binary Tree
    LeetCode OJ 111. Minimum Depth of Binary Tree
    LeetCode OJ 110. Balanced Binary Tree
    apache-jmeter-3.1的简单压力测试使用方法(下载和安装)
    JMeter入门教程
    CentOS6(CentOS7)设置静态IP 并且 能够上网
    分享好文:分享我在阿里8年,是如何一步一步走向架构师的
  • 原文地址:https://www.cnblogs.com/yeshengCqupt/p/13508202.html
Copyright © 2011-2022 走看看