leetcode-5-最长回文子串-三种解法

  1. 最长回文子串
    给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。

示例 1:

输入: “babad”
输出: “bab”
注意: “aba” 也是一个有效答案。
示例 2:

输入: “cbbd”
输出: “bb”、

第一:暴力解法:看代码注释很容易理解
时间复杂度:因为主程序有2个for循环,掉用的函数还有一次n循环,总的时间复杂度是N的3方

class Solution {
    /**
     * 暴力解法:这个函数是判断当前传进来的子串是不是回文子串,就是从两边向中间依次判断
     * @param charArray:当前字符串数组
     * @param left:左边界
     * @param right:右边界
     * @return 当前边界条件下是否是回文子串
     */
    public boolean validSym(char[] charArray, int left, int right){
        while(left < right){
            if (charArray[left] != charArray[right]) {
                return false;
            }
            left++;
            right--;
        }
        return true;
    }

    /**
     *暴力解法:从第一个自负开始,依次向后判断当前的范围是不是回文子串,调用上面的函数
     * @param s : 字符串
     * @return: 返回最长的回文子串
     */
    public String longestPalindrome(String s) {
        char[] charArray = s.toCharArray();
        int char_len = charArray.length;
        if (char_len < 2) return s;

        int max_len = 1;
        int begin = 0;
        for (int i = 0; i < char_len-1; i++) {
            for (int j = i+1; j < char_len; j++) {
                if (j-i+1>max_len && this.validSym(charArray, i, j )){
                    max_len = j-i+1;
                    begin = i;
                }
            }
        }
        return s.substring(begin, begin + max_len);  // 注意这个子串函数是左闭右开,右边取不到
    }
}

第二种方法:中心开花方法,从中心向两边扩散,分别寻找当前下标的最长回文子串
分为两种情况,有可能是偶数串,也有可能是奇数串

/**
     * 从当前给定的左右两个下标开始,从中心向两边扩散,l 和 r可能相等活不相等
     * @param charArray:原字符数组
     * @param left:中心点下标
     * @param right|:中心点下表
     * @return 返回满足要求的左右边界下标
     */
    public int[] expendFromCenter(char[] charArray, int left, int right){
        int char_len = charArray.length;

        while (left>=0 && right < char_len && charArray[left] == charArray[right]){
            left--;
            right++;
        }

        int[] a = new int[2];
        a[0] = left + 1;
        a[1] = right - 1;
        return a;
    }

    /**
     * 对于·每一个下标,分别求一下当前下标情况下的奇数回文子串 和 偶数回文淄川的长度分别是多少
     * @param s:字符串
     * @return 返回所有下标的最长回文子串
     */
    public String longestPalindrome(String s){
        char[] charArray= s.toCharArray();
        int char_len = charArray.length;
        if (char_len < 2) return s;

        int max_len = 1;
        int begin = 0;
        for (int i = 0; i < char_len; i++) {
            int[] oddCenter = this.expendFromCenter(charArray, i, i);  // 把当前中心点作为奇数中心
            int[] evenCenter = this.expendFromCenter(charArray, i, i+1);  // 把当前中心点作为偶数中心

            if (oddCenter[1]-oddCenter[0]+1 > max_len && oddCenter[1]-oddCenter[0]+1 > evenCenter[1]-evenCenter[0]+1){
                begin = oddCenter[0];
                max_len = oddCenter[1] - oddCenter[0] + 1;
            }else if (evenCenter[1]-evenCenter[0]+1 > max_len && evenCenter[1]-evenCenter[0]+1 > oddCenter[1]-oddCenter[0]+1){
                begin = evenCenter[0];
                max_len = evenCenter[1] - evenCenter[0] + 1;
            }
        }
        return s.substring(begin, begin + max_len);
    }

方法三:动态规划的解法:
在这里插入图片描述
在这里插入图片描述
dp数组保存ij是否是回文子串的boolean值
长度小于2,化简之后就是坐标关系的小于3

class Solution {
    public String longestPalindrome(String s){
        char[] charArray = s.toCharArray();
        int char_len = charArray.length;
        if (char_len < 2) return s;

        int max_lem = 1;
        int begin = 0;
        boolean[][] dp = new boolean[char_len][char_len];  // 初始化dp数组
        for (int i = 0; i < char_len; i++) {
            dp[i][i] = true;
        }

        
        // 构建dp数组:按照每一列构建
        for (int j = 0; j < char_len; j++) {  // 列在这里面是后移动项
            for (int i = 0; i < j; i++) {  // 行这里面是先移动项
                if (charArray[i] != charArray[j]) {
                    dp[i][j] = false;
                }else if (j - i < 3) {
                    dp[i][j] = true;
                }else {
                    dp[i][j] = dp[i+1][j-1];
                }

                if (dp[i][j] == true && j - i + 1 > max_lem) {
                    max_lem = j - i + 1;
                    begin = i;
                }
            }
        }
        return s.substring(begin, begin + max_lem);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值