21.1:最长回文子序列

在这里插入图片描述

给定一个字符串str,返回这个字符串的最长回文子序列长度

比如 : str = “a12b3c43def2ghi1kpm”

最长回文子序列是“1234321”或者“123c321”,返回长度7

一:暴力递归

	/**
     * 暴力递归
     */
    public static int lpsl1(String s) {
        if (s == null || s.length() == 0) {
            return 0;
        }
        char[] str = s.toCharArray();
        return process(str, 0, str.length - 1);
    }

    //str[0 .... tail]
    //返回最长回文子序列的长度
    public static int process(char[] str, int start, int tail) {
        if (start == tail) {
            return 1;
        }
        if (start == tail - 1) {
            //这个1很机灵
            return str[start] == str[tail] ? 2 : 1;
        }

        //s 是  t 不是
        int res1 = process(str, start, tail - 1);

        //s 不是  t 是
        int res2 = process(str, start + 1, tail);

        //s 不是  t 不是
        int res3 = process(str, start + 1, tail - 1);

        //s 是  t 是
        int res4 = str[start] == str[tail] ? 2 + process(str, start + 1, tail - 1) : 0;

        return Math.max(Math.max(res1, res2), Math.max(res3, res4));
    }

迭代版本

    public static int lpsl2(String s) {
        if (s == null || s.length() == 0) {
            return 0;
        }
        int N = s.length();
        char[] str = s.toCharArray();
        int[][] dp = new int[N][N];
        for (int i = 0; i < N; i++) {
            dp[i][i] = 1;
        }
        for (int l = 1; l < N; l++) {
            dp[l - 1][l] = str[l - 1] == str[l] ? 2 : 1;
            for (int c = l - 2; c >= 0; c--) {
                int res1 = dp[c][l - 1];
                int res2 = dp[c + 1][l];
                int res3 = dp[c + 1][l - 1];
                int res4 = str[c] == str[l] ? 2 + dp[c + 1][l - 1] : 0;
                dp[c][l] = Math.max(Math.max(res1, res2), Math.max(res3, res4));
            }
        }
        return dp[0][N - 1];
    }

进一步优化

在这里插入图片描述

由上图可知左下一定是最小的,即左下一定小于等于左与下

	public static int lpsl3(String s) {
        if (s == null || s.length() == 0) {
            return 0;
        }
        int N = s.length();
        char[] str = s.toCharArray();
        int[][] dp = new int[N][N];
        for (int i = 0; i < N; i++) {
            dp[i][i] = 1;
        }
        for (int l = 1; l < N; l++) {
            dp[l - 1][l] = str[l - 1] == str[l] ? 2 : 1;
            for (int c = l - 2; c >= 0; c--) {
                int res1 = dp[c][l - 1];//left
                int res2 = dp[c + 1][l];//down
                //因为左下一定小于等于右或者下,所以可以直接的舍去。
                //int res3 = dp[c + 1][l - 1];//leftdown
                int res4 = str[c] == str[l] ? 2 + dp[c + 1][l - 1] : 0;
                dp[c][l] = Math.max(Math.max(res1, res2), res4);
            }
        }
        return dp[0][N - 1];
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

橙-橙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值