5.Longest Palindromic Substring(59.30%)

题目:Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring.

个人理解:求给定字符串的最长回文。
我首先想到的是从左到右找出该字符串里的所有回文,然后每次都比较找到的回文,保存最长的那条。这种方法是很笨的,因为它把所有相邻的字符串组合都查了个遍,结果虽然正确,但是超时了。

public class Solution {
    public String longestPalindrome(String s) {
        char[] inputArray = s.toCharArray();
        int length = inputArray.length;

        if (length == 0) {
                return "";
        }

        if (length == 1) {
                return s;
        }

        String longestPalidrome = "";
        for (int i = 0; i < length; i++) {
                for (int j = i + 1; j < length; j++) {
                    // 从i位向后寻找
                    for (int k = i, m = j;; k++, m--) {
                        if (inputArray[k] == inputArray[m]) {
                            // 有可能是回文
                            if (k >= m) {
                                // 这是一个回文,和之前的回文对比,看看哪条长,保存最长的,然后返回上层循环继续寻找
                                String tempPalidrome = new String(s.substring(i, j + 1));
                                longestPalidrome = longestPalidrome.length() > tempPalidrome.length() ? longestPalidrome : tempPalidrome;
                                break;
                            } else {
                                // 有可能是回文,继续当前循环的寻找工作
                                continue;
                            }
                        } else {
                            // 不是回文,返回上一层循环继续寻找
                            break;
                        }
                    }
                }
        }

            return longestPalidrome.length() < 2 ? String.valueOf(inputArray[length - 1]) : longestPalidrome;
    }
}

后来我就想,不要傻傻地列出所有的字符串组合,再去判断是不是回文,是不是最长回文,我直接从回文的中心去找回文字符串,找到直接判断是不是最长的不久行了吗?找到方向之后,分析一下,发现回文其实就是分两种情况,一种是字符个数为奇数,一种是字符个数是偶数,然后就开始写代码了:

public class Solution {
    public String longestPalindrome(String s) {
        char[] inputArray = s.toCharArray();
        int length = inputArray.length;
        int longestIndex = length - 1;

        if (length == 0) {
                return "";
        }

        if (length == 1) {
                return s;
        }

        int longestBegin = 0;
        int longestEnd = 0;
        int longestLength = 1;
        // 找出所有单枢纽回文比较之,i就是枢纽
        int i = 1;
        while (i < longestIndex) {

                int j = i - 1, k = i + 1;
                while (j >= 0 && k < length) {
                    if (inputArray[j] != inputArray[k]) {
                        // 当前不是回文了
                        break;
                    }
                    j--;
                    k++;
                }
                // 更新找到回文信息
            int tempPalindromeLength = (k - 1) - (j + 1) + 1;
            if (longestLength < tempPalindromeLength) {
                longestLength = tempPalindromeLength;
                longestBegin = j + 1;
                longestEnd = k - 1;
            }

                i++;
        }

        // 找出所有双枢纽回文比较之
        int u = 0;
        while (u < longestIndex) {
                // x是枢纽1,y是枢纽2
                int x = u, y = u + 1;

                // 定义一个标志来记住是否是真正的双枢纽
                boolean isRealDoublePivot = true;
                while (x >= 0 && y < length) {
                    if (inputArray[x] != inputArray[y]) {
                        // 当前不是回文了
                        if (y - x == 1) {
                            // 不是真正的双枢纽
                            isRealDoublePivot = false;
                        }
                        break;
                    }
                    x--;
                    y++;
                }
                // 找到的确实是双枢纽,更新回文信息
                if (isRealDoublePivot) {
                    int tempPalindromeLength = (y - 1) - (x + 1) +1;
                    if (longestLength < tempPalindromeLength) {
                        longestLength = tempPalindromeLength;
                        longestBegin = x + 1;
                        longestEnd = y - 1;
                    }
                }

                u++;
        }

        return longestLength < 2 ? String.valueOf(inputArray[0]) : s.substring(longestBegin, longestEnd + 1);
    }
}

后来脑袋闪过一个念头,我们的目的不是求最长的回文吗?回文长度再长,也长不过我们输入的字符串,那么我们假设最长回文的长度就是输入的字符串长度,如果假设被推翻,我们就假设最长回文的长度是输入字符串长度-1。如此递减地找,找到的那条,肯定是最长的了,因为我们的假设是从最长开始的。这样也是可以通过的,不过速度好像没有第二种方案快?

public class Solution {
    public String longestPalindrome(String s) {
        char[] inputArray = s.toCharArray();
        int length = inputArray.length;
        int longestIndex = length - 1;

        if (length == 0) {
                return "";
        }

        if (length == 1) {
                return s;
        }

        // 回文的长度再怎么长也长不过输入的字符串长度
        for (int palindromeLen = length; palindromeLen > 0; palindromeLen--) {
                if (palindromeLen % 2 == 0) {
                    // 回文长度为偶数,枢纽的坐标为palindromeLen/2-1,palindromeLen/2到length-palindromeLen/2-1,length-palindromeLen/2
                    for (int i = palindromeLen/2-1, j = length-palindromeLen/2-1; i <= j; i++) {
                        int m = i, n = i + 1;
                    while (m >= 0 && n <= longestIndex) {
                        // 中心两个数相等,那么向两边扩散
                            if (inputArray[m] == inputArray[n]) {
                                if (n - m == palindromeLen - 1) {
                                    // 找到最长的回文字符串了
                                    return s.substring(m, n + 1);
                                }
                                m--;
                                n++;
                            } else {
                                // 还没到达指定的长度就不相等了,跳出当前枢纽的扩散操作,转战下一个枢纽
                                break;
                            }
                    }
                    }
                } else {
                    // 回文长度为奇数,枢纽的坐标为palindromeLen/2到length-palindromeLen/2-1
                    for (int i = palindromeLen/2, j = length-palindromeLen/2-1; i <= j; i++) {
                        int m = i - 1, n = i + 1;
                    while (m >= 0 && n <= longestIndex) {
                        // 中心两个数相等,那么向两边扩散
                            if (inputArray[m] == inputArray[n]) {
                                if (n - m == palindromeLen - 1) {
                                    // 找到最长的回文字符串了
                                    return s.substring(m, n + 1);
                                }
                                m--;
                                n++;
                            } else {
                                // 还没到达指定的长度就不相等了,跳出当前枢纽的扩散操作,转战下一个枢纽
                                break;
                            }
                    }
                    }
                }
        }

        return String.valueOf(inputArray[0]);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

ithouse

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

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

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

打赏作者

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

抵扣说明:

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

余额充值