- 題目一:最長連續回文子串。
- 問題分析:回文串顧名思義表示前后讀起來都是一樣,這里面又是需要連續的。分析這個問題的結構,可以想到多種方法。暴力解決的方式,2層循環遍歷得出各個子串,然后再去判斷該子串是否回文,這樣的話O(N)=n的三次方,還有一種是dp解決。
- 解題方法一:暴力解決的方法。前面已經講到了方法,下面給出方法的實現。
class Solution { public: string longestPalindrome(string s) { int maxlength = 0; int start = 0, end = 0; for (int i=0; i<s.size(); i++){ for (int j=i+1; j<s.size(); j++){ int temp1, temp2; for (temp1=i, temp2=j; temp1<temp2; temp1++, temp2--){ if (s[temp1] != s[temp2]) break; } if (temp1>=temp2 && j-i>maxlength){ maxlength = j-i+1; start = i; end = j; } } } if (maxlength > 0) s.substr(start, maxlength); return NULL; } };
- 解題方法二:DP求解。為什么會想到dp求解呢。首先分析問題。最長連續子串是否回文。如果一個子串回文,那么子串的子串也就是回文的,依次類推就簡化為一個小的解,從而得到整體的解。
具體思路:設置一個int二維數組DP[i][j]用來存儲從i到j的串是否回文,1表示是,0表示否。
這里有三種情況需要考慮:①:當只有一個字符的時候,i=j,肯定回文 DP[i][j] = 1;
②:當兩個兩個字符相鄰的時候,如果他們相等,那么他們也是回文的,i-j<2 && s[i]==s[j] -> DP[i][j] = 1
③:當超過兩個字符的時候,如果他們首尾是相同的並且除去首尾字符的剩余字符也是回文的話,那么這個串也是回文的。
s[i] == s[j] && DP[i+1][j-1] = 1 ->DP[i][j] = 1
考慮完這三種情況,就設置兩個指針記錄最長回文子串的左右位置,然后直接提取出來即可。DP[i][j] = 1 並且最長字符長度小於當前字符長度。 -
class Solution { public: string longestPalindrome(string s) { int dp[s.size()][s.size()] ; int left = 0, right = 0, maxlength = 0; for (int i=0; i<s.size(); i++){ for (int j=0; j<i; j++){ //這里表示出了所有的情況 //當為相鄰兩個字符串時,如果相等則為1,當大於兩個字符串時,如果首尾相同並且子串是回文的話,那么這個串也是回文 dp[j][i] = (s[i] == s[j] && ((i-j < 2) || dp[j+1][i-1])); if (dp[j][i] && maxlength< i-j+1) { maxlength = j-i+1; left = j; right = i; } } dp[i][i] = 1;//這里表示單個字符串就是回文串。 } return s.substr(left, right-left+1); } };
- 問題分析:回文串顧名思義表示前后讀起來都是一樣,這里面又是需要連續的。分析這個問題的結構,可以想到多種方法。暴力解決的方式,2層循環遍歷得出各個子串,然后再去判斷該子串是否回文,這樣的話O(N)=n的三次方,還有一種是dp解決。
- 題目二:給出一個整數,判斷這個整數是否是回文數字,不能使用額外的存儲空間,意思是不能將他變為字符串。
- 題目分析:第一想到的就是將他變成一個字符串然后對他進行判斷是否是回文串。但是題目不能變為字符串。這里我們就可以變換一種方法。比如對數字“12321”,12321/10000=1,首位為1, 12321%10=1,尾部為1,然后繼續判斷232這個數字,按照相同的方法(這里的關鍵是剩余數字的位數需要確定)
- 代碼:
class Solution { public: bool isPalindrome(int x) { if (x < 0) return false; int flag = 1; while(x/flag >= 10){//求整數的最高位 -》這是求最高位的位數的技巧 flag *= 10; } while (x) { int left = -1, right = -1; left = x/flag; right = x%10; if (left != right) return false; x = (x%flag)/10; flag = flag/100; } return true; } };
- 題目分析:第一想到的就是將他變成一個字符串然后對他進行判斷是否是回文串。但是題目不能變為字符串。這里我們就可以變換一種方法。比如對數字“12321”,12321/10000=1,首位為1, 12321%10=1,尾部為1,然后繼續判斷232這個數字,按照相同的方法(這里的關鍵是剩余數字的位數需要確定)
- 題目三:判斷一個字符串是否是回文,只考慮字母和數字,其他空格之類的忽略。
- 思路:這個就是簡答的判斷字符串是否是回文的情況。碰到不是字母或者是數字的情況直接跳轉到下一個字符串,頭尾依次進行比較。這里需要考慮大小寫的問題,所以比較是否相同直接利用assic的值進行比較比較合適。s[left] +32 -'a')%32 != (s[right] +32 -'a')%32 ->>這里%32表示大小寫的assic 32是一個循環。
- 代碼
class Solution { public: bool isPalindrome(string s) { int len = s.size(); int left = 0, right = len-1; while (left < right){ if (!isAlphaNum(s[left])) left++; else if (!isAlphaNum(s[right])) right--; else if((s[left] +32 -'a')%32 != (s[right] +32 -'a')%32) return false;//這里考慮到大小寫,所以直接這樣用assic進行比較 else{ left++,right--; } } return true; } bool isAlphaNum(char &ch) { if (ch >= 'a' && ch <= 'z') return true; if (ch >= 'A' && ch <= 'Z') return true; if (ch >= '0' && ch <= '9') return true; return false; } };
- 思路:這個就是簡答的判斷字符串是否是回文的情況。碰到不是字母或者是數字的情況直接跳轉到下一個字符串,頭尾依次進行比較。這里需要考慮大小寫的問題,所以比較是否相同直接利用assic的值進行比較比較合適。s[left] +32 -'a')%32 != (s[right] +32 -'a')%32 ->>這里%32表示大小寫的assic 32是一個循環。
- 題目四:
給定一個字符串s,分區s使得分區的每個子字符串是一個回文。 返回s的所有可能的回文分區。 例如,給定s =“aab”, 返回 [ [“aa”,“b”], [“a”,“a”,“b”] ]]
- 題目分析:實際上這道題目是一道組合的題目,對付組合的題目,回溯法是一個很好的方法。這里是要拆分字符串(拆分的串都是回文串),得出所有的拆分情況。組合問題->回溯法,DFS算法很好的解決了這個問題。先是針對一個一個字符進行拆分,然后是針對兩個字符是回文串的串,之后是含有三個字符是回文串的字符,依次類推(這里需要一個函數是判斷該字符串是否為回文的函數,給定首尾進行判斷)。dfs遞歸的條件是找到符合要求的回文串,然后對后面的串也進行遞歸的求解(從頭開始繼續進行遞歸求解)
- 實例分析:
a b c e e -> 第一組:a 回文 a進temp, b回文 b進temp, c 回文 c進temp , e 回文 e進temp , e 回文 e進temp找到一組,出容器。
第二組:回溯,回溯到第一個e,進行兩個字符回文查找判斷,找到ee,之后就沒有了。 - 代碼:
class Solution { public: vector<vector<string>> partition(string s) { vector<vector<string> > res; vector<string> temp; partition(s, 0, temp, res); return res; } void partition(string &s, int start, vector<string> temp, vector<vector<string> > &res){ int len = s.size(); if (start == len) res.push_back(temp); for (int i=start; i<len; i++){ if (isPalindromeStr(s, start, i)){ temp.push_back(s.substr(start, i-start+1)); partition(s, i+1, temp, res); temp.pop_back(); } } } bool isPalindromeStr(string s, int start, int end){ while (start < end){ if (s[start] != s[end]){ return false; }else start++,end--; } return true; } };