美文网首页
动态规划

动态规划

作者: 欢西西西 | 来源:发表于2023-02-21 21:11 被阅读0次

1. 三角形最小路径和

image.png

dp[i][j]表示以i, j 位置的点为起点到达最低端的最小路径的和
状态方程:dp[i][j] = triangle[i][j] + min(dp[i+1][j], dp[i+1][j+1])
边界:i 到达最后一行

// 这里只写了思路,可以再缓存一下结果优化递归调用
function minTrace(triangle) {
    var lth = triangle.length;
    if(!lth) { return 0;}
    if (lth === 1) {
        return triangle[0][0];
    }
    const minTr = function(i, j) {
        if (i === lth - 1) { return triangle[i][j]; }  // 边界  
        return triangle[i][j] + Math.min(minTr(i + 1, j), minTr(i + 1, j + 1));
    }
    return minTr(0, 0);
}

2. 字符串的编辑问题

image.png

dp[i][j]表示的是:strA的前i下标位的字符变化到strB的前j下标位字符的编辑距离

        if (a[i] === b[j]) {
          dp[i][j] =  dp(i - 1, j - 1); // 如果2个字符相等,编辑距离不会增加       
        }

        let v1 = dp(i - 1, j - 1) + 1, // 替换
            v2 = dp(i, j - 1) + 1, // 删除
            v3 = dp(i - 1, j ) + 1; // 插入

       dp[i][j] = Math.min(v1, v2, v3);
image.png - -
情况1:替换 image.png -情况2:删除 image.png -情况3: 插入 image.png

3. 字符串中回文子串的数量

image.png

dp[i, j] 表示字符串从i到j位是否是回文,值标记为布尔值
如果str[i] !== str[j],则dp[i][j] = false
如果str[i] === str[j], 则 dp[i][j]取决于dp[i+1][j-1]是否为true

一些边界条件:
i === j即只有一个字符时,是回文
j-i === 1 && str[i] === str[j]即只有2个字符且他俩相等时,是回文

image.png

4. 字符串中的最长回文子串的长度

仍是上题的思路,修改点是当str[i, j]是回文时,dp[i][j]存字符长度,不是回文时dp[i][j] = 0

let i = lth // i从最后一位往前遍历
let dp = []; // dp[i, j]:从i到j位的字符如果是回文,就存字符长度,如果不是,就为0
while (i >= 0) {
    if (!dp[i]) {
        dp[i] = {};
    }
    let j = i; // 这里很重要,我们定义j>=i,则j从i开始往后遍历
    while (j <= lth) {
        if (i === j) {
            // 如果只有一个字符串,就是回文,长度为1
            dp[i][j] = 1;
        } else if (j - i === 1 && line[i] === line[j]) {
            // 如果是2个字符串且2个字符相等,就是回文,长度为2
            dp[i][j] = 2;
        } else if (line[i] === line[j] && dp[i + 1][j - 1] > 0) {
            // 3个字符及以上
            dp[i][j] = 2 + dp[i + 1][j - 1]; // 这2个字符的长度+str[i+1][j-1]的长度
        }
        j++;
    }
    i--;
}
let max = 0;
dp.forEach(d => {
    Object.values(d).forEach(v => {
        if (v > max) { max = v }
    })
});
// console.log(dp)
console.log(max)

5. 合唱队

N 位同学站成一排,音乐老师要请最少的同学出列,使得剩下的 K 位同学排成合唱队形。

  • 请最少的人出列,即求人数最多的合唱队形
  • 计算每位同学左侧的最长递增子序列的长度,以及右侧的最长递减子序列的长度
  • 这个题最主要的是要明确:如何求i之前 / 之后的最长递增/递减子序列
  • 如果 dp[i]表示i之前的最长递增子序列的长度,那么dp[i] = 1 + max (i前面每一个小于它的项的最长递增子序列的长度)
image.png

6. 字符串中最长回文子序列的长度

需要跟子串区别的是,子串是连续的,子序列可以不连续

  • dp[i][j]表示从i到j位的最长回文子序列的长度
  • str[i] === str[j]时,dp[i][j] = dp[i+1][j-1]+2
  • str[i] !== str[j]时,dp[i][j] = max (dp[i][j-1], dp[i+1][j]]) 这是跟回文子串最不一样的地方,回文子串是不判断i位和j位不相等的情况的

7. 打家劫舍

给定一个数组例如 [1, 5, 4],每项表示每个房间的钱币数量,不能偷相邻房间的钱,问最多能偷多少钱

  • dp[i]表示前i位范围的房间内最多能偷多少钱
  • 当第i个房间确定要偷时,它的前一个房间就不能偷,dp[i] = money[i] + dp[i-2]
  • 当不偷第i个房间时:dp[i] = dp[i-1]
  • 最终:dp[i] = max(money[i] + dp[i-2], dp[i-1])

升级版:

将第一个房间和最后一个房间连在一起,形成环,其他条件不变

image.png

相关文章

网友评论

      本文标题:动态规划

      本文链接:https://www.haomeiwen.com/subject/uayzhdtx.html