LeetCode刷题笔记 - 5. 最长回文子串

学好算法很重要,而后要学好算法,大量的练习是必不可少的,LeetCode是我常常去的一个刷题网站,上面的题目很是详细,各个标签的题目都有,能够总体练习,本公众号后续会带你们作一作上面的算法题。算法

官方连接:https://leetcode-cn.com/problemset/all/ide


1、题意

难度:中等网站

https://leetcode-cn.com/problems/longest-palindromic-substring/url

给定一个字符串 s,找到 s 中最长的回文子串。你能够假设 s 的最大长度为 1000。spa

示例code

输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。

输入: "cbbd"
输出: "bb"


2、解题

方法一:暴力法

  • 依次枚举全部子串判断他们是不是回文
class Solution {
    public String longestPalindrome(String s) {
        int len = s.length();
        if(len < 2) {
            return s;
        }
        
        int max = 1;
        int begin = 0;
        
        char[] charArr = s.toCharArray();
        
        for(int i = 0; i < len - 1; ++i) {
            for(int j = i + 1; j < len; ++j){
                // 判断当前子串是否大于最大值且为回文串
                if(j - i + 1 > max && valid(charArr, i, j)){
                    // 更新值
                    max = j - i + 1;
                    begin = i;
                }
            }
        }
        // 返回结果
        return s.substring(begin, begin + max);
    }

    /**
     * 回文串校验
     */
    public boolean valid(char[] c, int left, int right) {
        while(left < right){
            if(c[left++] != c[right--]){
                return false;
            }
        }
        return true;
    }
}

复杂度分析:orm

  • 时间复杂度:O(n^3)
  • 空间复杂度:O(1)


方法二:中心扩散法

  • 中心位置出发,尽量的扩散出去,获得一个回文数
  • 注意奇数与偶数长度的回文
class Solution {
    public String longestPalindrome(String s) {
        int len = s.length();
        if(len < 2) {
            return s;
        }
        
        int max = 1;
        int begin = 0;
        
        char[] charArr = s.toCharArray();
        
        for(int i = 0; i < len - 1; ++i) {
            // 获取奇数,偶数回文串的长度
            int odd = expandAroundCenter(charArr, i, i);
            int even = expandAroundCenter(charArr, i, i + 1);
            
            // 更新状态
            int curMax = Math.max(odd, even);
            if(curMax > max){
                max = curMax;
                begin = i - (max - 1) / 2;
            }
        }
        
        // 返回结果
        return s.substring(begin, begin + max);
    }

    /**
    * 获取回文串长度
    */
    private int expandAroundCenter(char[] c, int left, int right){
        int len = c.length;
        int i = left;
        int j = right;
        // 根据中心点往两边延伸,获取最长回文串区间
        while(i >= 0 && j < len && c[i] == c[j]){
            i--;
            j++;
        }
        
        // 返回结果
        return j - i - 1;
    }
}

复杂度分析:leetcode

  • 时间复杂度:O(n^2)
  • 空间复杂度:O(1)


方法三:动态规划

  • 若是里面的子串是回文,总体就是回文串
  • 若是里面的子串不是回文串,总体就不是回文串
public class Solution {
    public String longestPalindrome(String s) {
        int len = s.length();
        if (len < 2) {
            return s;
        }

        int maxLen = 1;
        int begin = 0;

        // dp[i][j] 表示 s[i, j] 是不是回文串
        boolean[][] dp = new boolean[len][len];
        char[] charArray = s.toCharArray();

        // 初始化
        for (int i = 0; i < len; i++) {
            dp[i][i] = true;
        }
        
        for (int j = 1; j < len; j++) {
            for (int i = 0; i < j; i++) {
                // 判断是否为回文
                if (charArray[i] != charArray[j]) {
                    dp[i][j] = false;
                } else {
                    // 间距小于3则为true,大于3则根据上一区间结果进行赋值
                    if (j - i < 3) {
                        dp[i][j] = true;
                    } else {
                        dp[i][j] = dp[i + 1][j - 1];
                    }
                }

                // 只要 dp[i][j] == true 成立,就表示子串 s[i..j] 是回文,此时记录回文长度和起始位置
                if (dp[i][j] && j - i + 1 > maxLen) {
                    maxLen = j - i + 1;
                    begin = i;
                }
            }
        }
        return s.substring(begin, begin + maxLen);
    }
}

复杂度分析:字符串

  • 时间复杂度:O(n2)
  • 空间复杂度:O(n2)
相关文章
相关标签/搜索