class Solution {
public:
bool isPalindrome(int x) {
//算出x的倒置数a,比较a是否和x相等就行了
int a = 0, b = x;
while(b > 0){
a = a * 10 + b % 10;
b /= 10;
}
if(a == x)
return true;
else
return false;
}
};
判断字符串回文
class Solution {
public:
bool isPalindrome(string s) {
int left = 0, right = s.size() - 1 ;
while (left < right) {
if (!isalnum(s[left])) ++left;
else if (!isalnum(s[right])) --right;
else if ((s[left] + 32 - 'a') %32 != (s[right] + 32 - 'a') % 32) return false;//toupper()
else {
++left; --right;
}
}
return true;
}
};
class Solution {
public:
bool isPalindrome(string s) {
int left = 0, right = s.size() - 1 ;
while (left < right) {
if (!isalnum(s[left])) ++left;
else if (!isalnum(s[right])) --right;
else if (toupper(s[left])!= toupper(s[right])) return false;//toupper()
else {
++left; --right;
}
}
return true;
}
};
Longest Palindromic Substring 最长回文串
这道题让我们求最长回文子串,首先说下什么是回文串,就是正读反读都一样的字符串,比如 “bob”, “level”, “noon” 等等。那么最长回文子串就是在一个字符串中的那个最长的回文子串。LeetCode中关于回文串的题共有五道,除了这道,
其他的四道为 Palindrome Number 验证回文数字, Validate Palindrome 验证回文字符串, Palindrome Partitioning 拆分回文串,Palindrome Partitioning II 拆分回文串之二,
我们知道传统的验证回文串的方法就是两个两个的对称验证是否相等,那么对于找回文字串的问题,就要以每一个字符为中心,像两边扩散来寻找回文串,这个算法的时间复杂度是O(n*n),可以通过OJ,就是要注意奇偶情况,由于回文串的长度可奇可偶,比如”bob”是奇数形式的回文,”noon”就是偶数形式的回文,两种形式的回文都要搜索,参见代码如下:
解法一:
// Time complexity O(n*n)
class Solution {
public:
string longestPalindrome(string s) {
int startIdx = 0, left = 0, right = 0, len = 0;
for (int i = 0; i < s.size() - 1; ++i) {
if (s[i] == s[i + 1]) {
left = i;
right = i + 1;
searchPalindrome(s, left, right, startIdx, len);
}
left = right = i;
searchPalindrome(s, left, right, startIdx, len);
}
if (len == 0) len = s.size();
return s.substr(startIdx, len);
}
void searchPalindrome(string s, int left, int right, int &startIdx, int &len) {
int step = 1;
while ((left - step) >= 0 && (right + step) < s.size()) {
if (s[left - step] != s[right + step]) break;
++step;
}
int wide = right - left + 2 * step - 1;
if (len < wide) {
len = wide;
startIdx = left - step + 1;
}
}
};
此题还可以用动态规划Dynamic Programming来解,根Palindrome Partitioning II 拆分回文串之二的解法很类似,我们维护一个二维数组dp,其中dp[i][j]表示字符串区间[i, j]是否为回文串,当i = j时,只有一个字符,肯定是回文串,如果i = j + 1,说明是相邻字符,此时需要判断s[i]是否等于s[j],如果i和j不相邻,即i - j >= 2时,除了判断s[i]和s[j]相等之外,dp[j + 1][i - 1]若为真,就是回文串,通过以上分析,可以写出递推式如下:
dp[i, j] = 1 if i == j
= s[i] == s[j] if j = i + 1
= s[i] == s[j] && dp[i + 1][j - 1] if j > i + 1
这里有个有趣的现象就是如果我把下面的代码中的二维数组由int改为vector
// DP
class Solution {
public:
string longestPalindrome(string s) {
int dp[s.size()][s.size()] = {0}, left = 0, right = 0, len = 0;
for (int i = 0; i < s.size(); ++i) {
for (int j = 0; j < i; ++j) {
dp[j][i] = (s[i] == s[j] && (i - j < 2 || dp[j + 1][i - 1]));
if (dp[j][i] && len < i - j + 1) {
len = i - j + 1;
left = j;
right = i;
}
}
dp[i][i] = 1;
}
return s.substr(left, right - left + 1);
}
};
最后要来的就是大名鼎鼎的马拉车算法Manacher’s Algorithm,这个算法的神奇之处在于将时间复杂度提升到了O(n)这种逆天的地步,而算法本身也设计的很巧妙,很值得我们掌握,参见我另一篇专门介绍马拉车算法的博客Manacher’s Algorithm 马拉车算法,代码实现如下:
解法三:
class Solution {
public:
string longestPalindrome(string s) {
string t ="$#";
for (int i = 0; i < s.size(); ++i) {
t += s[i];
t += '#';
}
int p[t.size()] = {0}, id = 0, mx = 0, resId = 0, resMx = 0;
for (int i = 0; i < t.size(); ++i) {
p[i] = mx > i ? min(p[2 * id - i], mx - i) : 1;
while (t[i + p[i]] == t[i - p[i]]) ++p[i];
if (mx < i + p[i]) {
mx = i + p[i];
id = i;
}
if (resMx < p[i]) {
resMx = p[i];
resId = i;
}
}
return s.substr((resId - resMx) / 2, resMx - 1);
}
};
class Solution {
public:
void getPalindrome(string& s, int left, int right, int &out1,int &out2)
{
if (left < right && s[left] != s[right]) {
out1 = out2 = left;
return;
}
int size = s.size();
while (left > 0 && (right + 1 < size) && s[left-1] == s[right+1]) {
left--;
right++;
}
out1 = left;
out2 = right;
}
string longestPalindrome(string s) {
int size = s.size();
int left = 0;
int len = 1;
for (int i = 0; i < size; i++) {
int l, r;
getPalindrome(s, i, i, l, r);
if (r - l+1 > len) {
len = r - l + 1;
left = l;
}
getPalindrome(s, i, i+1, l, r);
if (r > l && r - l + 1 > len) {
len = r - l + 1;
left = l;
}
}
return s.substr(left, len);
}
};
//分两种情况,奇数和偶数,奇数情况:中间一个不同,其他两边相同,
//偶数情况,中间两个相同
int testTwoSides(string &s, int low, int up)
{
int n = s.length();
int max = 0;
if (low == up)
{
low--;
up++;
max = 1;
}
while (low>=0 && up<n && s[low] == s[up])
{
max+=2;
low--;
up++;
}
return max;
}
string longestPalindrome(string s)
{
int n = s.length();
int subStartPoint = 0;
int maxLength = 1;
int temp = 0;
for (int i = 0; i < n; i++)
{
temp = testTwoSides(s, i, i);
if (temp > maxLength)
{
subStartPoint = i - temp/2;
maxLength = temp;
}
}
for (int i = 1; i < n; i++)
{
temp = testTwoSides(s, i-1, i);
if (temp > maxLength)
{
subStartPoint = i - temp/2;
maxLength = temp;
}
}
return s.substr(subStartPoint, maxLength);
}
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
class Solution {
public:
string longestPalindrome(string s) {
const int n=s.size();
bool dp[n][n];
fill_n(&dp[0][0],n*n,false);
int max_len=1; //保存最长回文子串长度
int start=0;//保存最长回文子串起点
for(int i=0;i<s.size();++i)
{
for(int j=0;j<=i;++j)
{
if(i-j<2)
dp[j][i]=(s[i]==s[j]);
else
dp[j][i]=(s[i]==s[j] && dp[j+1][i-1]);
if(dp[j][i] && max_len<(i-j+1))
{
max_len=i-j+1;
start=j;
}
}
}
return s.substr(start,max_len);
}
};
int _tmain(int argc, _TCHAR* argv[])
{
string input;
Solution sln;
while(cin>>input)
{
cout<<"最长回文子串为:"<<sln.longestPalindrome(input)<<endl;
}
return 0;