好久没刷题了,为了准备秋招,面了几家公司提前感受面试氛围,一直在背八股文~
后面不打算再面了,还是要回归基础~
今天炒个冷饭,看一下回文子串的问题,奇怪的是leetcode这个题我竟然没有写过 0 . 0

题目短的可怜,证明它真的简单的很多人不屑去做。。
思路:
一、中心扩展法,直接上代码,没有什么好解释的
- class Solution {
- public:
- string longestPalindrome(string s) {
- int n=s.size();string s1,s2;
- int result=INT_MIN;
- if(n==0||n==1)return s;
- for(int index=0;index<n;index++)
- {
- int left=index;
- int right=index;
- int num1=1;
- while(left>=0&&right<n){
- if(s[left]==s[right])
- {
- if(left!=right)num1+=2;
- if(num1>=s1.size())s1=s.substr(left,num1);
- }
- else break;
- left--;
- right++;
- }
- }
- for(int index=0;index<n;index++)
- {
- int indey=index+1;
- int index_1=index;
- int index_2=indey;
- int num2=0;
- while(index_1>=0&&index_2<n&&s[index_1]==s[index_2]){
- num2+=2;
- if(num2>=s2.size())s2=s.substr(index_1,num2);
- index_1--;index_2++;
- }
- }
- return s1.size()>s2.size()?s1:s2;
- }
- };

所以,重复子问题,就是去判断 子串是否是回文串。
动规五部曲:
1.dp[i][j]含义:表示 s 下标 从 i 到 j 是否为回文串;
2.初始化:每一个字符都是一个回文子串
3.递推公式:考虑边界条件:如果字符串长度为 2、3,只要保证 s[i]==s[j]就可判断 它是回文
4.遍历:从前往后
5.打印dp
代码:
- class Solution {
- public:
- string longestPalindrome(string s) {
- if(s.size()==1)return s;
- int begin=0;
- int maxlen=1;
- vector<vector<int>>dp(s.size(),vector<int>(s.size()));
- //dp 表示 s 从 i 到 j 是否为回文子串;
- for(int i=0;i<s.size();i++)dp[i][i]=1;//初始化,本身肯定是回文串
- for(int length=2;length<=s.size();length++)
- {
- for(int leftindex=0;leftindex<s.size();leftindex++)
- {
- int rightindex=length+leftindex-1;
- if(rightindex>=s.size())break;//如果右边界越界了就跳出
- //如果 左右边界值不等 显然不能为回文串
- if(s[leftindex]!=s[rightindex])dp[leftindex][rightindex]=0;
- else{// 奇数 AbA保证左右相等就行 偶数 AA 保证 左右相等就行
- if(rightindex-leftindex<=2)dp[leftindex][rightindex]=1;
- else{//如果字符串长度>3,递归判断前面一个子串是否是回文串
- dp[leftindex][rightindex]=dp[leftindex+1][rightindex-1];
- }
- }
- //找到了一个回文串就更新一次 begin 与 maxlen
- if(dp[leftindex][rightindex]&&rightindex-leftindex+1>maxlen){
- maxlen=rightindex-leftindex+1;
- begin=leftindex;
- }
- }
- }
- return s.substr(begin,maxlen);
- }
- };
遍历不太符合正常的动规方法,个人感觉不如 中心扩展法来的实在,毕竟空间复杂度都是O(n^2)