【JS力扣刷题笔记】516. 最长回文子序列

这是跟着代码随想录的顺序学习算法的第?天。

以下是学习时自己的一些理解与笔记,如有错误欢迎指正与讨论。


516. 最长回文子序列

参考相关链接:

516. 最长回文子序列

代码随想录


笔记

题目要求计算最长的回文子序列的长度,因此,这里就定义 dp[i][j] 来表示区间 [i, j] 内的最长回文子序列。

接着,再看看题目的要求,是求长度,而不是具体的最长子串是什么,这是很关键的一点,如果没有深刻理解这一点,就容易在思考的时候陷入误区,把解题方向弄成了如何去确定该区间构成的最长回文子串是什么,具体是需要删除什么来构成的。


事实上,我们并不关心如何构成,我们只关心区间内最长回文子串的长度。


先考虑两种情况,区间两端的元素相同即 s[i] === s[j] ,这说明,不论区间内剩余区间即 [i + 1, j - 1] 的最长回文子串的长度是多少都可以在这个回文子串的两端同时加上两个相同的元素,这能保证其依旧是回文串,并且长度加了 2


接着,考虑区间两端的元素不相同即 s[i] !== s[j] ,这说明,,不论区间内剩余区间即 [i + 1, j - 1] 的最长回文子串的长度是多少都不能在这个回文子串的两端同时加上两个相同的元素,因为加了就必定不是回文串,故只能加其中一个,也就是说,此时区间的最长回文子串的长度,会和 [i + 1, j] 或者 [i, j - 1] 其中的一个区间的最长回文子串的长度相同。

在这第二种情况中,其实选取其中一个子区间的操作就是一种删除操作


后面就按照卡哥的 DP 五步法进行初始化,遍历,和测试就可以了。


值得一提的是,这里的初始化,主要就是考虑到了 i === j 的情况没有办法用上面的方法处理,因为此时的区间长度为 1 ,而上面的两种情况的处理都是在默认区间长度至少为 2 的前提下进行的,故需要单独处理一下。

// 代码随想录 JS 版本
const longestPalindromeSubseq = (s) => {
    const strLen = s.length;
    let dp = Array.from(Array(strLen), () => Array(strLen).fill(0));
    
    for(let i = 0; i < strLen; i++) {
        dp[i][i] = 1;
    }

    for(let i = strLen - 1; i >= 0; i--) {
        for(let j = i + 1; j < strLen; j++) {
            if(s[i] === s[j]) {
                dp[i][j] = dp[i+1][j-1] + 2;
            } else {
                dp[i][j] = Math.max(dp[i+1][j], dp[i][j-1]);
            }
        }
    }

    return dp[0][strLen - 1];
};

你可能感兴趣的:(javascript,学习,算法,leetcode,前端)