zoukankan      html  css  js  c++  java
  • LeetCode——最长回文子序列

    Q:给定一个字符串s,找到其中最长的回文子序列。可以假设s的最大长度为1000。

    示例 1:
    输入:
    "bbbab"
    输出:
    4
    一个可能的最长回文子序列为 "bbbb"。

    示例 2:
    输入:
    "cbbd"
    输出:
    2
    一个可能的最长回文子序列为 "bb"。

    A:
    引用自:《labuladong的算法小抄》
    取决于 s[i] 和 s[j] 的字符:
    如果它俩相等,那么它俩加上 s[i+1..j-1] 中的最⻓回⽂⼦序列就是s[i..j] 的最⻓回⽂⼦序列:

    如果它俩不相等,说明它俩不可能同时出现在 s[i..j] 的最⻓回⽂⼦序列中,那么把它俩分别加⼊ s[i+1..j-1] 中,看看哪个⼦串产⽣的回⽂⼦序列更⻓即可:

    if (s[i] == s[j])
    // 它俩⼀定在最⻓回⽂⼦序列中
    dp[i][j] = dp[i + 1][j - 1] + 2;
    else
    // s[i+1..j] 和 s[i..j-1] 谁的回⽂⼦序列更⻓?
    dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]);
    

    ⾸先明确⼀下 base case,如果只有⼀个字符,显然最⻓回⽂⼦序列⻓度是1,也就是 dp[i][j] = 1 (i == j) 。
    因为 i 肯定⼩于等于 j ,所以对于那些 i > j 的位置,根本不存在什么⼦序列,应该初始化为 0。另外,看看刚才写的状态转移⽅程,想求 dp[i][j] 需要知道 dp[i+1][j-1] , dp[i+1][j] , dp[i][j-1] 这三个位置;再看看我们确定的 basecase,填⼊ dp 数组之后是这样:

    为了保证每次计算 dp[i][j] ,左下右⽅向的位置已经被计算出来,只能斜着遍历或者反着遍历

    选择反着遍历:

        public static int longestPalindromeSubseq(String s) {
            int size = s.length();
            if (size == 0)
                return 0;
            int[][] dp = new int[size][size];
            for (int i = 0; i < size; i++) {
                dp[i][i] = 1;
            }
            //反着遍历
            for (int i = size - 2; i >= 0; i--) {
                for (int j = i + 1; j < size; j++) {
                    if (s.charAt(i) == s.charAt(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][size - 1];
        }
    
  • 相关阅读:
    复习总结
    python 之Tornado
    MySQL 同一Windows系统上安装多个数据库
    CSS 轻松搞定元素(标签)居中问题
    Linux 解决Deepin深度系统无法在root用户启动Google Chrome浏览器的问题
    Django Windows+IIS+wfastcgi 环境下部署
    Django RestFramework(DRF)类视图
    php+ajax实现拖动滚动条分批加载请求加载数据
    Jquery+php鼠标滚动到页面底部自动加载更多内容,使用分页
    jQuery+ajax实现滚动到页面底部自动加载图文列表效果
  • 原文地址:https://www.cnblogs.com/xym4869/p/12584727.html
Copyright © 2011-2022 走看看