leetcode 5. 最长回文子串

本题也是中等题中做的不熟的,主要需要掌握三种做法:

1.暴力,枚举所有的子串,并对所有的子串进行validate,那么时间复杂度是O(n^3)

2.枚举中心,然后向两边扩展,计算当前中心的最大回文子串长度:时间复杂度是O(n^2)

class Solution {
    private int len;
    private char[] c;
    // 返回以c1,c2为下标的中心对应的回文串的最大长度
    private int helper(int c1,int c2){
        int l=c1==c2?1:2;
        while((--c1>=0)&&(++c2<len)){
            if(c[c1]!=c[c2]){
                break;
            }
            l+=2;
        }
        return l;
    }
    public String longestPalindrome(String s) {
        if(s==null||s.length()==0){
            return s;
        }
        len=s.length();
        c=s.toCharArray();
        int max=1;
        int start=0;
        for(int i=0;i<len-1;i++){
            int oddlen=helper(i,i);
            int evenLen=c[i]==c[i+1]?helper(i,i+1):0;
            if(oddlen>max){
                start=i-oddlen/2;
                max=oddlen;
                
            }
            if(evenLen>max){
                start=i-evenLen/2+1;
                max=evenLen;
            }
        }
        return s.substring(start,start+max);
    }
}

写代码时遇到一个问题:明明错乱,比如两个变量,一个用来保存字符串的长度,一个用来保存当前回文子串的长度,我竟然都命名为len,这种bug一定要避免,一般来说,变量名的长度应该根据作用域的大小来设置,越大,越长

3.dp:递推关系,如果一个子串[i,j]是回文串,并且s[i-1]==s[j+1],那么[i-1,j+1]也是回文子串

这里使用dp[i][j]来表示[i,j]是否是回文子串,因为i<=j,所以我们要填的就是一个上三角,并且主对角线上因为代表单个字符的字符串,所以都是回文串.此外,我们要保证dp[i][j]在dp[i-1][j+1]之前计算,即填表应该是行从大到小,列从小到大

当然本题dp的性能并不比2好,同样的O(n^2)的时间复杂度,空间却是O(n^2)

class Solution {
    public String longestPalindrome(String s) {
        if(s==null||s.length()==0){
            return s;
        }
        int len=s.length();
        char[] c=s.toCharArray();
        boolean[][] dp=new boolean[len][len];
        int max=1;
        int start=0;
        for(int j=0;j<len;j++){
            for(int i=j;i>=0;i--){
                if(i==j){
                    dp[i][j]=true;
                }else{
                    if((j-i)==1){
                        dp[i][j]=c[i]==c[j];
                    }else{
                        dp[i][j]=dp[i+1][j-1]&&c[i]==c[j];
                    }
                }
                if(dp[i][j]&&(j-i+1)>max){
                    max=j-i+1;
                    start=i;
                }
            }
        }
        return s.substring(start,start+max);
    }
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值