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];
        }
    
  • 相关阅读:
    iis部署网站打不开
    微信小程序全选多选效果
    清除浮动
    IIS_常见问题及解决方法
    文字闪烁效果
    IIS 伪静态 脚本映射 配置方法
    批量删除QQ空间说说
    自定义input文件上传 file的提示文字及样式
    使用google api material icons在网页中插入图标
    jquery日期插件jquery.datePicker参数
  • 原文地址:https://www.cnblogs.com/xym4869/p/12584727.html
Copyright © 2011-2022 走看看