leetCode 5.Longest Palindromic Substring 解题思路与方法

问题:

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, and there exists one unique longest palindromic substring.


这个题是真的花了很多的时间,刚开始思路是对的,将回文字符串按中心向两侧循环读取,不相等即break,然后记录字符串和长度,依次循环,直到找到最优解。

提交的时候知道效率不高,因为未对全文同一字符做甄别处理。

代码如下:

public class Solution {
    public String longestPalindrome(String s) {
        char[] c = s.toCharArray();
        String t = "";//最大回文字符串
        String temp = "";//暂时存放回文字符串
        int len = 0;//回文长度
        int max = 0;//最大回文长度
        int j,k;
        for(int i = 0; i < c.length;i++){
            j = i;
            k = i;
            temp = c[i] + "";
            //如果未超过数组界限
            while(j > 0 && k < c.length - 1){
                if(c[--j] == c[++k]){
                    temp = c[j] + temp + c[k];
                }else{
                    j++;
                    k--;
                    break;
                }
            }
            len = k - j + 1;
            if(max < len){
                max = len;
                t = temp;
            }
        }
        return t;
    }
}

第一次就错误了,因为未考虑偶数回文字符串的情况,继续处理。

public class Solution {
    public String longestPalindrome(String s) {
        char[] c = s.toCharArray();
        //System.out.println(c.length);
        String t = "";//最大回文字符串
        String temp1 = "";//暂时存放回文字符串
        String temp2 = "";//暂时存放回文字符串
        int len = 0;//回文长度
        int max = 0;//最大回文长度
        int j,k;
        boolean isAddI = false;
        for(int i = 0; i < c.length;i++){
            j = i;
            k = i;
            temp1 = c[i] + "";
            temp2 = "";
            
            //判断单字符情况
            char tempChar = c[i];
            int oneCharLen = 1;
            while(j < c.length - 1 && tempChar == c[++j]){
        		oneCharLen++;
        	}
            //回文字符为奇数
            j = i;
            while(j > 0 && k < c.length - 1){
                if(c[--j] == c[++k]){
                    temp1 = c[j] + temp1 + c[k];
                }else{
                    j++;
                    k--;
                    break;
                }
            }
            len = k - j + 1;
           //回文字符为偶数
            j = i+1;
            k = i;
            while(j > 0 && k < c.length - 1){
                if(c[--j] == c[++k]){
                    temp2 = c[j] + temp2 + c[k];
                }else{
                    j++;
                    k--;
                    break;
                }
            }
            //判断奇数还是偶数回文长
            if(len < k - j + 1){
            	len = k - j + 1;
            	temp1 = temp2;
            }
            
            //与最大回文数比较
            if(max < len){
                max = len;
                t = temp1;
            }
            
            //与单字符回文比较
            if(max < oneCharLen){
            	t = "";
            	max = oneCharLen;
            	for(int m=0; m < oneCharLen;m++){
            		t += tempChar;
            	}
            }
            //如果是单字符,无需重复比较,直接跳到字符中间
            if(oneCharLen > 4 && !isAddI){
            	i += oneCharLen/2 - 2;
            	isAddI = true;//每次i值跳转之后最少要前进两个位置
            }else{
            	isAddI = false;
            }
            
            if(max == c.length){
                break;
            }
        }
        return t;
    }
}

这一次考虑了偶数回文以及单字符的情况,如果字符在一定范围内相等,则跳转到字符中间再开始,相等于二分法,方法上效率已经不错了,但是执行上效率依然不高,。最后对执行优化,把 temp1 = c[j] + temp1 + c[k];这样的字符串操作去掉,改为jj和kk回文开始和结束的位置标记,最后一次赋值提交,这样大大优化,单次1000个ab这样的字符串可以25ms内解出,比优化之前的150ms左右的时间大大优化。

最终的代码(整体用时336ms):

public class Solution {
    public String longestPalindrome(String s) {
        char[] c = s.toCharArray();
        //统一奇数回文串和偶数回文串
        System.out.println(c.length);
        String t = "";//最大回文字符串
        int len = 0;//回文长度
        int max = 0;//最大回文长度
        int j,k;
        int jj = 0,kk = 0;
        char tempChar;
        int oneCharLen = 1;
        boolean isAddI = false;
        for(int i = 0; i < c.length;i++){
            j = i;
            k = i;
            
            //判断单字符情况
            tempChar = c[i];
            oneCharLen = 1;
            while(j < c.length - 1 && tempChar == c[++j]){
        		oneCharLen++;
        	}
            //System.out.println("oneCharLen-->" + oneCharLen);
            //与单字符回文比较
            if(max < oneCharLen){
            	max = oneCharLen;
            	jj = i;
            	if(tempChar == c[j])
            		kk = j;
            	else
            		kk = j-1;
            }
            //回文字符为奇数
            j = i;
            while(j > 0 && k < c.length - 1){
                if(c[--j] != c[++k]){
                    j++;
                    k--;
                    break;
                }
            }
            len = k - j + 1;
            if(len > max){
            	max = len;
            	jj = j;
            	kk = k;
            }
           //回文字符为偶数
            j = i+1;
            k = i;
            while(j > 0 && k < c.length - 1){
                if(c[--j] != c[++k]){
                    j++;
                    k--;
                    break;
                }
            }
            //判断长度
            len = k - j + 1;
            if(len > max){
            	max = len;
            	jj = j;
            	kk = k;
            }
            //如果是单字符,无需重复比较,直接跳到字符中间
            if(oneCharLen > 4 && !isAddI){
            	i += oneCharLen/2 - 2;
            	isAddI = true;//每次i值跳转之后最少要前进两个位置
            }else{
            	isAddI = false;
            }
            if(max == c.length){
            	break;
            }
        }
        for(int i = jj; i <= kk;i++){
        	t += c[i];
        }
        return t;
    }
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值