博客
关于我
47:礼物的最大值(动态规划)
阅读量:790 次
发布时间:2023-01-23

本文共 2123 字,大约阅读时间需要 7 分钟。

m*n 棋盘最大礼物价值问题 solution

在一个 m*n 的棋盘中,每个格子都有一个礼物,每个礼物都有一个价值。我们需要从起点 (0,0) 只能向右或向下走,直到走到右下角 (m-1, n-1),求出沿途所经过的礼物的最大价值。

解决思路

这个问题类似于经典的动态规划问题,可以通过动态规划的方法来解决。目标是找到从起点到终点路径中礼物价值的最大总和。由于只能向右或向下走,所以每个格子的最大价值取决于其左边格子和上边格子的最大值再加上当前格子的礼物价值。

具体来说,我们可以使用一个二维数组 maxGift,其中 maxGift[i][j] 表示到达格子 (i,j) 时的最大礼物价值。在这个数组的基础上,我们可以逐步计算每个格子的最大价值。

  • 初始化 maxGift[0][0] 为起点处的礼物价值。
  • 从起点开始,逐步向右和向下遍历整个棋盘。
  • 对于每一个格子 (i,j),它的最大价值 maxGift[i][j] = 左边格子 (i,j-1) 的最大价值 maxGift[i][j-1] 和上边格子 (i-1,j) 的最大价值 maxGift[i-1][j]中的较大者,再加上当前格子的礼物价值。
  • 这种方法需要一个二维数组来存储中间结果,空间复杂度为 O(mn),时间复杂度为 O(mn)。

    优化空间复杂度

    在上述基础上,我们可以通过将 maxGift 换成一个一维数组来优化空间复杂度。具体做法如下:

  • 创建一个一维数组 maxGift,其中 maxGift[j] 表示上一行的第 j 个格子的最大价值。
  • 使用同样的遍历方式,逐步向右和向下遍历整个棋盘。
  • 对于当前行的第 j 个格子,取决于它是否在当前行的第一个位置:
    • 如果是,最大价值就是上一行第一个格子的最大价值加上当前格子的礼物价值。
    • 如果不是,最大价值就是上一行第 j 个格子和当前行第 j-1 个格子的最大价值中的较大者,再加上当前格子的礼物价值。
  • 同时更新当前行的最大值数组 maxGift,用于后续计算。
  • 这种优化后的方法将空间复杂度降低到 O(n) ,时间复杂度仍为 O(mn)。

    ##代码示例

    public int func(int[][] gifts) {    if (gifts == null || gifts.length == 0)        return 0;    // 使用一维数组优化空间复杂度    int n = gifts[0].length;    int[] maxGift = new int[n];    maxGift[0] = gifts[0][0];    for (int i = 1; i < gifts.length; i++) {        for (int j = 0; j < n; j++) {            int up = 0;            if (i > 0)                up = maxGift[j];                        int left = 0;            if (j > 0)                left = maxGift[j - 1];                        maxGift[j] = Math.max(up, left) + gifts[i][j];        }    }    return maxGift[n - 1];}

    优化后的空间复杂度 solution

    为了进一步优化空间复杂度,我们可以直接将 maxGift 数组重新划分,仅记录必要的信息,而不存储整个二维数组。这通过将上一行的最大值存储在一个一维数组中实现,节省了额外的 O(n) 空间。

    以下是优化后的 Java 实现:

    public int func2(int[][] gifts) {    if (gifts == null || gifts.length == 0)        return 0;    int n = gifts[0].length;    int[] maxGift = new int[n];    maxGift[0] = gifts[0][0];    for (int i = 1; i < gifts.length; i++) {        for (int j = 0; j < n; j++) {            int up = (i > 0) ? maxGift[j] : Integer.MIN_VALUE;            int left = (j > 0) ? maxGift[j - 1] : Integer.MIN_VALUE;                        maxGift[j] = Math.max(up, left) + gifts[i][j];        }    }    return maxGift[n - 1];}

    这个优化后的方法不仅节省了空间,还保持了相同的时间复杂度 O(mn)。

    转载地址:http://aieyk.baihongyu.com/

    你可能感兴趣的文章
    matlab cross()函数叉乘 计算过程详解
    查看>>
    46:把数字翻译成字符串(动态规划)
    查看>>
    47:礼物的最大值(动态规划)
    查看>>
    49天精通Java,第28天,Java lambda表达式
    查看>>
    49天精通Java,第42天,java stream流详解,从集合遍历,看stream流操作
    查看>>
    500套精美Logo样机模板可直接套用、轻松制作炫酷logo
    查看>>
    centos7上安装 mysql
    查看>>
    5小时内使用DeepSeek写出一篇优质论文的三步攻略指南
    查看>>
    60天新媒体公众号写作秘诀
    查看>>
    C#多线程编程系列(五)- 使用任务并行库
    查看>>
    ASP.NET MVC4 json序列化器
    查看>>
    Android 版本更新之打开apk文件的前生今世
    查看>>
    6410_Linux系统系统移植 和 驱动加载
    查看>>
    64位WIN7+oracle11g+plsql安装
    查看>>
    6天掌握mysql基础视频教程
    查看>>
    7 Tips For Better JDeveloper Experience
    查看>>
    70. 爬楼梯
    查看>>
    7B2 PRO主题5.4.2免授权直接安装
    查看>>
    7大常用JCL 模板
    查看>>
    111
    查看>>