1. 题目:

  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.

注:

palindromic substring :回文序列,如:aba,abba 等。

2.1   C++    暴力解决—— 时间复杂度O(N³)

思路:

(1).  构造一个map,存储原字符出现的所有位置;

(2). 从头到位扫描字符串,根据map中的位置,选取子字符串,判断是否为回文序列

class Solution {
public:
    string longestPalindrome(string s) {
        unsigned long long string_len=s.length();
        if(string_len==0)
            return "";
        if(string_len==1)
            return s;
        string current_str="",longest_str="";
        unsigned long long current_len=0,longest_len=0;
        map<char,vector<unsigned long long> >char_pos_map;
         
        for(int i=0;i<string_len;i++){
            map<char,vector<unsigned long long> >::iterator char_pos_map_it=char_pos_map.find(s[i]);  
            if(char_pos_map_it==char_pos_map.end()) {   
                vector<unsigned long long> pos_list;   
                pos_list.push_back(i);   
                char_pos_map.insert(pair<char, vector<unsigned long long > >((char)s[i],pos_list));   
            } else {   
                vector<unsigned long long> & pos_list=char_pos_map_it->second;   
                pos_list.push_back(i);   
            }   
        }                                      //map存储每个字符出现的位置
         
       
        for(int index_head = 0;index_head<string_len;index_head++) {   
            std::map<char, vector<unsigned long long > >::iterator it = char_pos_map.find(s[index_head]);   
            if( it->second.size()==1) {   
                current_len = 1;   
                current_str = s[index_head];   
                if(current_len>longest_len) {   
                      longest_str = current_str;   
                      longest_len = current_len;                          //只出现一次的字符         
                }

} else {                       
                vector<unsigned long long> & tmp_vec = it->second;                   
                unsigned long long index_num =  tmp_vec.size();   
                unsigned long long tmp_index_head =  index_head;   
                for(long long j=(long long)(index_num-1);j>=0;j--) {   
                    tmp_index_head = index_head;   
                    unsigned long long tmp_index_tail = tmp_vec[j];   
                     
                    if(tmp_index_tail<tmp_index_head)   
                        continue;   
                    current_len = tmp_index_tail-tmp_index_head+1;   
                    if( current_len==0 || current_len < longest_len)   
                        continue;   
                         
                    current_str = s.substr(tmp_index_head, current_len);        //取子字符串,验证是否为回文字符
                    while( ((long long)(tmp_index_tail-tmp_index_head)>=1) && (s[tmp_index_tail]==s[tmp_index_head]) ) {

tmp_index_head++;   
                        tmp_index_tail--;   
                    }

if( ((long long)(tmp_index_tail-tmp_index_head)==-1) || (tmp_index_tail-tmp_index_head==0) ){       //奇数  偶数个字符的情况
                        longest_len = current_len;   
                        longest_str = current_str;   
                    }   
                       
                }   
            }   
        }   
        return longest_str;   
    }   
};

2.2  动态规划

删除暴力解法中有很多重复的判断。很容易想到动态规划,时间复杂度O(n^2),空间O(n^2),动态规划方程如下:

  • dp[i][j] 表示子串s[i…j]是否是回文
  • 初始化:dp[i][i] = true (0 <= i <= n-1);  dp[i][i-1] = true (1 <= i <= n-1); 其余的初始化为false
  • dp[i][j] = (s[i] == s[j] && dp[i+1][j-1] == true)

在动态规划中保存最长回文的长度及起点即可

 
 
class Solution {
public:
    string longestPalindrome(string s) {
        const int len = s.size();
        if(len <= 1)return s;
        bool dp[len][len];               //dp[i][j]表示s[i..j]是否是回文
        memset(dp, 0, sizeof(dp));      //初始化为0
        int resLeft = 0, resRight = 0; 
        dp[0][0] = true;
 
        for(int i = 1; i < len; i++)
        {
            dp[i][i] = true;
            dp[i][i-1] = true;           //这个初始化容易忽略,当k=2时要用到
        }
 
        for(int k = 2; k <= len; k++)           //外层循环:枚举子串长度
            for(int i = 0; i <= len-k; i++)     //内层循环:枚举子串起始位置
            {
                if(s[i] == s[i+k-1] && dp[i+1][i+k-2])
                {
                    dp[i][i+k-1] = true;
                    if(resRight-resLeft+1 < k)
                    {
                        resLeft = i;
                        resRight = i+k-1;
                    }
                }
            }
        return s.substr(resLeft, resRight-resLeft+1);
    }
};

2.3 从中间向两边展开,时间复杂度O(n^2),空间O(1)

  回文字符串显然有个特征是沿着中心那个字符轴对称。比如aha沿着中间的h轴对称,a沿着中间的a轴对称。那么aa呢?沿着中间的空字符''轴对称。所以对于长度为奇数的回文字符串,它沿着中心字符轴对称,对于长度为偶数的回文字符串,它沿着中心的空字符轴对称。对于长度为N的候选字符串,我们需要在每一个可能的中心点进行检测以判断是否构成回文字符串,这样的中心点一共有2N-1个(2N-1=N-1 + N)。检测的具体办法是,从中心开始向两端展开,观察两端的字符是否相同

class Solution {
public:
    string longestPalindrome(string s) {
        const int len = s.size();
        if(len <= 1)return s;
        int start, maxLen = 0;
        for(int i = 1; i < len; i++)
        {
            //寻找以i-1,i为中点偶数长度的回文
            int low = i-1, high = i;
            while(low >= 0 && high < len && s[low] == s[high])
            {
                low--;
                high++;
            }
            if(high - low - 1 > maxLen)
            {
                maxLen = high - low -1;
                start = low + 1;
            }
             
            //寻找以i为中心的奇数长度的回文
            low = i- 1; high = i + 1;
            while(low >= 0 && high < len && s[low] == s[high])
            {
                low--;
                high++;
            }
            if(high - low - 1 > maxLen)
            {
                maxLen = high - low -1;
                start = low + 1;
            }
        }
        return s.substr(start, maxLen);
    }
};

java

两侧比较:

public class LongestPalindromicSubString1 {  

    /**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(longestPalindrome1("babcbabcbaccba"));
} public static String longestPalindrome1(String s) { int maxPalinLength = 0;
String longestPalindrome = null;
int length = s.length(); // check all possible sub strings
for (int i = 0; i < length; i++) {
for (int j = i + 1; j < length; j++) {
int len = j - i;
String curr = s.substring(i, j + 1);
if (isPalindrome(curr)) {
if (len > maxPalinLength) {
longestPalindrome = curr;
maxPalinLength = len;
}
}
}
} return longestPalindrome;
} public static boolean isPalindrome(String s) { for (int i = 0; i < s.length() - 1; i++) {
if (s.charAt(i) != s.charAt(s.length() - 1 - i)) {
return false;
}
} return true;
}
}

动态规划:

public class LongestPalindromicSubString2 {  

    public static String longestPalindrome2(String s) {
if (s == null)
return null; if(s.length() <=1)
return s; int maxLen = 0;
String longestStr = null; int length = s.length(); int[][] table = new int[length][length]; //every single letter is palindrome
for (int i = 0; i < length; i++) {
table[i][i] = 1;
}
printTable(table); //e.g. bcba
//two consecutive same letters are palindrome
for (int i = 0; i <= length - 2; i++) {
//System.out.println("i="+i+" "+s.charAt(i));
//System.out.println("i="+i+" "+s.charAt(i+1));
if (s.charAt(i) == s.charAt(i + 1)){
table[i][i + 1] = 1;
longestStr = s.substring(i, i + 2);
}
}
System.out.println(longestStr);
printTable(table);
//condition for calculate whole table
for (int l = 3; l <= length; l++) {
for (int i = 0; i <= length-l; i++) {
int j = i + l - 1;
if (s.charAt(i) == s.charAt(j)) {
table[i][j] = table[i + 1][j - 1];
if (table[i][j] == 1 && l > maxLen)
longestStr = s.substring(i, j + 1); } else {
table[i][j] = 0;
}
printTable(table);
}
} return longestStr;
}
public static void printTable(int[][] x){
for(int [] y : x){
for(int z: y){
//System.out.print(z + " ");
}
//System.out.println();
}
//System.out.println("------");
}
public static void main(String[] args) {
System.out.println(longestPalindrome2("1263625"));//babcbabcbaccba
}
}

leetcode--5 Longest Palindromic Substring的更多相关文章

  1. leetcode 第五题 Longest Palindromic Substring (java)

    Longest Palindromic Substring Given a string S, find the longest palindromic substring in S. You may ...

  2. leetcode第五题--Longest Palindromic Substring

    Problem:Given a string S, find the longest palindromic substring in S. You may assume that the maxim ...

  3. Leetcode:【DP】Longest Palindromic Substring 解题报告

    Longest Palindromic Substring -- HARD 级别 Question SolutionGiven a string S, find the longest palindr ...

  4. LeetCode(5)Longest Palindromic Substring

    题目 Given a string S, find the longest palindromic substring in S. You may assume that the maximum le ...

  5. [LeetCode] Longest Palindromic Substring 最长回文串

    Given a string S, find the longest palindromic substring in S. You may assume that the maximum lengt ...

  6. Leetcode Longest Palindromic Substring

    Given a string S, find the longest palindromic substring in S. You may assume that the maximum lengt ...

  7. 求最长回文子串 - leetcode 5. Longest Palindromic Substring

    写在前面:忍不住吐槽几句今天上海的天气,次奥,鞋子里都能养鱼了...裤子也全湿了,衣服也全湿了,关键是这天气还打空调,只能瑟瑟发抖祈祷不要感冒了.... 前后切了一百零几道leetcode的题(sol ...

  8. LeetCode 5 Longest Palindromic Substring(最长子序列)

    题目来源:https://leetcode.com/problems/longest-palindromic-substring/ Given a string S, find the longest ...

  9. 【JAVA、C++】LeetCode 005 Longest Palindromic Substring

    Given a string S, find the longest palindromic substring in S. You may assume that the maximum lengt ...

随机推荐

  1. vue中通过cross-env插件配置三种环境(开发,测试,生产)打包,不用切换api

    1. 话不多说,第一步就是安装必要的插件 npm install cross-env --save 2.修改config里面的参数,这里只展示一个test,其他类似 3.修改package.json ...

  2. PAT L2-014【二分】

    思路: 最后发现对当前列车比我大的编号的栈有没有就好了,所以开个vector存一下,然后二分一下vector找一下第一个比我大的数就好了 #include <bits/stdc++.h> ...

  3. CF 983B XOR-pyramid(区间dp,异或)

    CF 983B XOR-pyramid(区间dp,异或) 若有一个长度为m的数组b,定义函数f为: \(f(b) = \begin{cases} b[1] & \quad \text{if } ...

  4. 低价购买 dp

    题目描述 “低价购买”这条建议是在奶牛股票市场取得成功的一半规则.要想被认为是伟大的投资者,你必须遵循以下的问题建议:“低价购买:再低价购买”.每次你购买一支股票,你必须用低于你上次购买它的价格购买它 ...

  5. AT2382 A or...or B Problem

    传送门 还是看题解的啦 先考虑一个显而易见的结论:A和B二进制下最高的几位相同是没用的(设去掉的那些位之和为sum) 然后我们设\(d\)为二进制下从高位到低位第一位不相同的,\(k\)为B从高位到低 ...

  6. Java中的生产者和消费者实例(多线程 等待唤醒机制)

    1.什么是等待唤醒 我们实现的效果 创建生产者和消费者  对服装进行生产  和售卖 实现生产一个就消费一个 来观察线程的各种状态 下面是用到的方法: wait()方法:让一个线程进行等待 另外一个线程 ...

  7. Linux命令发送Http的get或post请求(curl和wget两种方法)

    Http请求指的是客户端向服务器的请求消息,Http请求主要分为get或post两种,在Linux系统下可以用curl和wget命令来模拟Http的请求.下面就来介绍一下Linux系统如何模拟Http ...

  8. Ubuntu批量修改文件后缀

    rename 's/\.JPG/.jpg/' *.JPG 把JPG后缀改为jpg 参考url====http://blog.csdn.net/whuslei/article/details/67249 ...

  9. 从客户端(content1="<img src="/web/news/...")中检测到有潜在危险的 Request.Form 值。

    在html编辑器里面加入图片提交的时候 就报一个 从客户端(content1="<img src="/web/news/...")中检测到有潜在危险的 Reques ...

  10. 使用原生javascript实现瀑布流

    简介 瀑布流布局是一种很常见的布局方式,他的主要视觉体验为图片元素等宽不等高,图片元素之间的水平排序参差不齐,而且随着滚动条的滚动,数据会进行异步的加载,这样的布局有两个好处,1-有视觉的冲击力,比较 ...