leetcode 回文系列 Palindrome

首先是经典的最长回文子串,Manacher给出了线性的算法。


Longest Palindromic Substring
 
AC Rate: 859/3674

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.

该算法在我另一篇博客中有介绍(传送门  http://blog.csdn.net/jiaowopan/article/details/9243195  ),这里就不再说明了。直接上代码


class Solution {
public:
    string longestPalindrome(string s) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        //use Manacher's Algorithm O(n)
        if(s.empty()) return s;
        int len = s.length();
		int i;
        //construct new string
        ostringstream ss;
        ss << "^";
        for(i = 0; i < len; ++i){
            ss<<"#"<<s[i];
        }
        ss<<"#$";
        string newstr = ss.str();
        len = newstr.length();
        vector<int> p(len,1);
        int mx(0),id(0),ans(1),center(0);
        for(i = 1; i < len-1; ++i){
            p[i] = (mx > i) ? min(p[2 * id - i], mx - i) : 1;
            while(newstr[i - p[i]] == newstr[i + p[i]]) p[i]++;
            if(i + p[i] > mx){//update mx and id
                mx = i + p[i];
                id = i;
            }
            if(p[i] > ans){//update ans and center
                center = i;
                ans = p[i];
            }
        }
        ans -= 1;
        return s.substr((center - ans - 1) / 2, ans);
    }
};


Valid Palindrome
 
AC Rate: 1046/4724

Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases.

For example,
"A man, a plan, a canal: Panama" is a palindrome.
"race a car" is not a palindrome.

Note:
Have you consider that the string might be empty? This is a good question to ask during an interview.

For the purpose of this problem, we define empty string as valid palindrome.


class Solution {
public:
    bool isPalindrome(string s) {
        // Note: The Solution object is instantiated only once and is reused by each test case.
        /*
        if(s.empty()) return true;
        stringstream ss;
        for(int i = 0; i < s.length(); ++i){
            if(isdigit(s[i]))
                ss<<s[i];
            else if(isupper(s[i])){
                ss<<char(s[i]+32);
            }
            else if(islower(s[i])){
                ss<<s[i];
            }
        }
        string cleanstr = ss.str();
        int len = cleanstr.length();
        if(0 == len)
            return true;
        int left = 0, right = len -1;
        while(left < right){
            if(cleanstr[left++] != cleanstr[right--])
                    return false;
        }
        return true;
        */
        //don't use extra string space
        if(s.empty())   return true;
        int len = s.length();
        int i(0), j(len-1);
        while( i < j){
            if(!isalnum(s[i])) ++i;
            else if(!isalnum(s[j])) --j;
            else{
                if(isupper(s[i])) s[i] += 32;
                if(isupper(s[j])) s[j] += 32;
                if(s[i] != s[j]) return false; 
                ++i;--j;
            } 
        }
        return true;
    }
};

Palindrome Number
 
AC Rate: 1028/3305

Determine whether an integer is a palindrome. Do this without extra space.

click to show spoilers.

Some hints:

Could negative integers be palindromes? (ie, -1)

If you are thinking of converting the integer to string, note the restriction of using extra space.

You could also try reversing an integer. However, if you have solved the problem "Reverse Integer", you know that the reversed integer might overflow. How would you handle such case?

There is a more generic way of solving this problem.

不使用额外空间是这个题的一个点,因此就要想办法获取第一位和最后一位。

class Solution {
public:
    bool isPalindrome(int x) {
        // Note: The Solution object is instantiated only once and is reused by each test case.
        if(x < 0) return false;
        int div = 1;
        while(x / div >= 10)
            div *= 10;
        while(x){
            int l = x /div;
            int r = x % 10;
            if(l != r)  return false;
            x = (x % div) / 10;
            div /= 100;
        }
        return true;
    }
};

Palindrome Partitioning
 
AC Rate: 807/3208

Given a string s, partition s such that every substring of the partition is a palindrome.

Return all possible palindrome partitioning of s.

For example, given s = "aab",
Return

  [
    ["aa","b"],
    ["a","a","b"]
  ]

这个题对时间的限制要求在判断是否是回文串的时候打个表记录一下,否则会超时。

用dp的思路去打表求ispa[i][j] , 然后用回溯得到所有可能的解。

class Solution {
public:
    vector<vector<string>> partition(string s) {
        // Note: The Solution object is instantiated only once and is reused by each test case.
        int len = s.length();
        if(0 == len) return vector<vector<string> >();
        vector<vector<bool> > ispa(len,vector<bool>(len,false));
        //build ispa with DP
        for(int i = 1; i <= len; ++i){
            for(int j = 0; j + i -1 < len; ++j){
                int k = j + i - 1;
                if(1 == i) ispa[j][j] = true;
                else if(2 == i) ispa[j][k] = (s[j] == s[k]);
                else
                    ispa[j][k] = ( s[j] == s[k] && ispa[j+1][k-1] );
            }
        }
        //backtracking to get solution
        vector<string> tmp;
        vector<vector<string> > ret;
        helper(s,0,tmp,ret,ispa);
        return ret;
    }
    void helper(const string &s, int pos, vector<string> &solution, vector<vector<string> > &result,const vector<vector<bool> > &ispa){
        if(pos == s.length()){
            result.push_back(solution);
            return;
        }
        for(int i = pos; i < s.length(); ++i){
            if(ispa[pos][i]){
                solution.push_back(s.substr(pos,i-pos+1));
                helper(s,i+1,solution,result,ispa);
                solution.pop_back();
            }
        }
        return;
    }
};

Palindrome Partitioning II
 
AC Rate: 765/4671

Given a string s, partition s such that every substring of the partition is a palindrome.

Return the minimum cuts needed for a palindrome partitioning of s.

For example, given s = "aab",
Return 1 since the palindrome partitioning ["aa","b"] could be produced using 1 cut.

这题我刚开始做的时候还是用dp求出一个二维回文标志数组,然后从头往后用bfs求跳到结尾的最小步数,可惜超时。看了讨论版才知道可以用dp,

而且代码可以如此的精简。

class Solution {
public:
    int minCut(string s) {
        // Note: The Solution object is instantiated only once and is reused by each test case.
        /*  TLE because of bfs
        //DP for calculating ispa and bfs for calculating result (TLE Yunk)
        int len = s.length();
        if(0 == len) return 0;
        vector<vector<bool> > ispa(len,vector<bool>(len,false));
        //build ispa with DP
        for(int i = 1; i <= len; ++i){
            for(int j = 0; j + i - 1 < len; ++j){
                int k = j + i - 1;
                if(1 == i)      ispa[j][j] = true;
                else if(2 == i)     ispa[j][k] = (s[j] == s[k]);
                else
                    ispa[j][k] = (s[j] == s[k] && ispa[j+1][k-1]);
            }
        }
    
        //calculate min cut
        //bfs from back to front
        queue<pair<int,int> > que;
        que.push(make_pair(len-1,0));
        while(!que.empty()){
            pair<int,int> p = que.front();
            que.pop();
            int id = p.first;
            int step = p.second;
            for(int j = 0; j <= id; ++j){
                if(ispa[j][id]){
                    if(j == 0){//can get final point
                        return step;
                    }
                    que.push(make_pair(j-1,step+1));
                }
            }
        }
        return -1;
        */
        
        //use dp to calculate mincut
        //dp[i] = min{ dp[j+1]+1 | j >= i && ispa[i][j] == true} 
        //from back to front ,result is dp[0] - 1
        int len = s.length();
        if(0 == len) return 0;
        vector<vector<bool> > ispa(len,vector<bool>(len,false));
        vector<int> dp(len+1);
        dp[len] = 0;
        for(int i = len-1; i >= 0; --i ){
            dp[i] = len - i;
            for(int j = i ; j < len; ++j){
                if(s[i] == s[j] && (j - i < 2 || ispa[i+1][j-1])){
                    ispa[i][j] = true;
                    dp[i] = min(dp[i], dp[j+1] + 1 );
                }
            }
        }
        return dp[0]-1;
        
    }
};


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值