算法打卡第九天 (动态规划)

151 阅读2分钟

问题

  1. 剑指 Offer 42. 连续子数组的最大和
  2. 剑指 Offer 47. 礼物的最大价值

剑指 Offer 42. 连续子数组的最大和

输入一个整型数组,数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。要求时间复杂度为O(n)。

题意分析: 查找数组中连续数之间最大的和(可能是一个也可能十多个)

  1. 声明两个变量,一个用来存储累计当前的最大和 maxAns,一个用来存储计算到当前的和pre
  2. 遍历数组,当前值加上pre>pre时,pre = pre + 当前值
  3. 当maxAns < pre 时,maxAns = pre
  4. 返回maxAns

测试用例 nums = [-2,1,-3,4,-1,2,1,-5,4] 输出: 6 解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。

var maxSubArray = function(nums) {
    if(!nums.length) return;
    let pre = 0, maxAns = nums[0];
    nums.forEach((x) => {
        pre = Math.max(pre + x, x);
        maxAns = Math.max(maxAns, pre);
    });
    return maxAns;
};

剑指 Offer 47. 礼物的最大价值

在一个 m*n 的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于 0)。你可以从棋盘的左上角开始拿格子里的礼物,并每次向右或者向下移动一格、直到到达棋盘的右下角。给定一个棋盘及其上面的礼物的价值,请计算你最多能拿到多少价值的礼物?

题意理解 二位数组从左上到右下,只能向右或向下走,返回累计最大的和

  1. 定义个变量用来存储走到每个点的左大值
  2. 从左上到右上只能从左到右走,可以计算出第一行走到每个位置的值
  3. 从左上到左下只能从上往下走,可以计算出福一列走到每个位置的值
  4. 然后开始计算第二行、第二列开始一次到每个点比较出的最大值
  5. 返回右下角数据

测试用例 输入: [ [1,3,1], [1,5,1], [4,2,1] ] 输出: 12 解释: 路径 1→3→5→2→1 可以拿到最多价值的礼物


    if(!grid.length){
        return 0
    }
    // 设置res 储存每个节点最大值的数组
    let res = []
    for(let i=0;i<grid.length;i++){
        res[i] = []
        for(let j =0;j<grid[0].length;j++){
            res[i][j] = 0
        }
    }
    // 算出向下走第一行的取值
    let m = 0
    for(let i =0;i<res.length;i++){
        m += grid[i][0]
        res[i][0] = m
    }
    let n = 0
    for(let i =0;i<res[0].length;i++){
        n += grid[0][i]
        res[0][i] = n
    } 
    for(let i=1;i<grid.length;i++){
        for(let j =1;j<grid[0].length;j++){
            res[i][j] = Math.max(res[i][j-1],res[i-1][j])+grid[i][j]
        }
    } 
    return res[grid.length-1][grid[0].length-1]