每日一题:LeetCode 算法题

616 阅读2分钟

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

示例:

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

来源:力扣(LeetCode)
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

暴力解法: 遍历判断:先从两边向内查找相等的字符 S(i,j)【表示第i个和第j个两个字符】,再判断S(i+1,j-1)是否相等。以此类推,直到i>=j。

public String longestPalindrome(String s) {
            char[] chars = s.toCharArray();
            int indexLeft = 0,indexRight = 0;
            for (int i = 0; i <chars.length ; i++) {
                for (int j = chars.length-1 ; j > i ; j--) {
                    if(chars[i]==chars[j]){
                        boolean palindrome = isPalindrome(s.substring(i, j+1));
                        if(palindrome&&j-i>indexRight-indexLeft){
                            indexLeft = i;
                            indexRight = j;
                            break;
                        }
                    }
                }
            }
            return s.substring(indexLeft,indexRight+1);

        }
        public boolean isPalindrome(String s){
            char[] chars = s.toCharArray();
            for (int i = 0; i <chars.length ; i++) {
                if(chars[i]==chars[chars.length-1-i] && s.length()>1){
                    if(!isPalindrome(s.substring(1,chars.length-1))){
                        return false;
                    }
                }else if(chars[i]!=chars[chars.length-1-i] ) {
                    return false;
                }
            }
            return true;
        }

毫无疑问的处理超时了。。。
原因分析:由于查找第一个相等的字符时进行了2重循环,判断是否为回文时进行了1次循环,所以他的时间复杂度为 O(n3)。(还未计算 递归算法。。。),只能用于提供思路,实操请绕行。

动态规划算法

由以上暴力解法中可以得知:如果F[i,j]是回文,那么F[i+1,j-1]也是回文。
F[i,j]=F[i+1,j1]+S[i,j]F[i,j] = F[i+1,j-1] + S[i,j]

  • i,j:表示第i个和第j个字符
  • S[i,j]:表示第i个和第j个字符是否回文,是为true,否为false
  • F[i,j]:表示从i到j的字符串是否回文,是为true,否为false
  • +号:表示代码中的 &&
public String longestPalindrome(String s) {
        int length = s.length();
        // 动态规划:F[i,j]=F[i+1,j−1] && S[i,j]
        boolean[][] dp = new boolean[length][length];
        int indexLeft = 0,indexRight = 0;
        //len 表示跨度 即选择的字符长度
        for (int len = 0; len < length ; len++) {
            for (int start = 0 ; start < length; start++) {
                int end = start+len;
                if(end<length){
                    if(len==0){
                        // len = 0 单个字符都是回文,所以全为true
                        dp[start][end] = true;
                    }else {
                        boolean flag = s.charAt(start) == s.charAt(end);
                        if(len == 1){
                            // len = 1 两个字符,直接判断是否相等即可
                            dp[start][end] = flag;
                        }else {
                            // 更多字符 判断当前字符是否为回文,还要判断上两个字符是否为回文
                            dp[start][end] = flag && dp[start + 1][end - 1];
                        }
                    }
                    if (dp[start][end] &&  end - start + 1 > indexRight-indexLeft) {
                        indexLeft = start;
                        indexRight = end+1;
                    }
                }
            }
        }
        return s.substring(indexLeft,indexRight);
    }

一顿操作猛如虎,一看超过九点五。。。

不服!再优化!