5. Longest Palindromic Substring (一)

5. Longest Palindromic Substring
Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.

Example 1:

Input: "babad"
Output: "bab"
Note: "aba" is also a valid answer.
Example 2:

Input: "cbbd"
Output: "bb"

给出一个字符串,得到这个字符串最大回文长度

首先先到的就是穷举法,贴下代码

    public static String longestPalindrome(String s) {
        StringBuilder result = null;
        char[] charArray = s.toCharArray();
        for (int i = 0; i < charArray.length; i++) {
            StringBuilder temp = new StringBuilder(s.substring(i, s.lastIndexOf(charArray[i]) + 1));
            getPalindrome(temp, result == null ? 0 : result.length());
            if (temp.length() > 0 && (result == null || temp.length() > result.length())){
                result = new StringBuilder(temp);
            }
        }
        return result == null ? String.valueOf(s.charAt(0)): result.toString();
    }

    private static void getPalindrome(StringBuilder temp, int resultSize){
        if (temp.length() <= 1 || temp.length() <= resultSize){
            return;
        }
        if (temp.toString().equals(temp.reverse().toString())){
            return;
        }

        temp.deleteCharAt(0);
        temp.reverse();
        getPalindrome(temp, resultSize);
    }

穷举法思路很简单,根据回文特征,从第一个字符开始,找到最后一个重复出现的位置,生成一个字符串,例如("qasqdqd"

---> "qasqdq" 判断是否是回文,如果不是,则找下一个重复出现的位置 ---> qasq 如果都不满足条件,则第一个字符就不用了,以次类推,直到找到最大长度的回文)

接下来优化的就是去掉一些无效的循环,减少循环次数:

其中StringBuilder的reverse方法频繁调用的问题,先看下StringBuilder的源码是怎么实现字符串反序的:

public AbstractStringBuilder reverse() {
        boolean hasSurrogates = false;
        int n = count - 1;
        for (int j = (n-1) >> 1; j >= 0; j--) {
            int k = n - j;
            char cj = value[j];
            char ck = value[k];
            value[j] = ck;
            value[k] = cj;
            if (Character.isSurrogate(cj) ||
                Character.isSurrogate(ck)) {
                hasSurrogates = true;
            }
        }
        if (hasSurrogates) {
            reverseAllValidSurrogatePairs();
        }
        return this;
    }

可以看到StringBuilder是通过循环字符串达到反序的,如果我们频繁调用reverse方法来进行回文判断,性能会受到巨大的影响,所以我们需要改变回文的判断方式。

    public static String longestPalindrome(String s) {
        StringBuilder result = null;
        char[] charArray = s.toCharArray();
        for (int i = 0; i < charArray.length; i++) {
            StringBuilder temp = new StringBuilder(s.substring(i, s.lastIndexOf(charArray[i]) + 1));
            getPalindrome(temp, result == null ? 0 : result.length());
            if (temp.length() > 0 && (result == null || temp.length() > result.length())){
                result = new StringBuilder(temp);
            }
        }
        return result == null ? String.valueOf(s.charAt(0)): result.toString();
    }

    private static void getPalindrome(StringBuilder temp, int resultSize){
        if (temp.length() <= 1 || temp.length() <= resultSize){
            return;
        }
        if (checkPalindrome(temp)){
            return;
        }
        getPalindrome(temp.deleteCharAt(temp.length() - 1), resultSize);
    }

    private static boolean checkPalindrome(StringBuilder temp){
        char[] charArrays = temp.toString().toCharArray();
        int end = charArrays.length / 2 - 1;
        for (int i = 0; i <= end; i++) {
            if (charArrays[i] != charArrays[charArrays.length - i - 1]){
                return false;
            }
        }
        return true;
    }

如果还要再进行优化的话,会发现需要把大量的系统方法改成自己编写的,费事费力,但是在做项目的时候,实现需求才是第一位的,在项目的实现过程中,安全性和性能都只能给业务让步,所以在没有想到更好的实现方式之前,最起码得把功能给实现出来。

但是如果需求对性能也有要求时,那就需要去寻找更加符合要求的解法,穷举法虽然在实现中是最简单也是最容易想到的方法,但是我们发现需要优化的地方实在太多太多了,这个时候就需要换一种思路进行解题。

点击查看新的解题思路

猜你喜欢

转载自blog.csdn.net/z89135898/article/details/80137048
今日推荐