新年的刷的第一题,题目以下:算法
给你一个字符串 s,找到 s 中最长的回文子串。网络
示例 1:函数
输入:s = "babad"
输出:"bab"
解释:"aba" 一样是符合题意的答案。
示例 2:ui
输入:s = "cbbd"
输出:"bb"
示例 3:spa
输入:s = "a"
输出:"a"
示例 4:code
输入:s = "ac"
输出:"a"
blog
提示:leetcode
1 <= s.length <= 1000
s 仅由数字和英文字母(大写和/或小写)组成字符串
来源:力扣(LeetCode)
连接:https://leetcode-cn.com/problems/longest-palindromic-substring
著做权归领扣网络全部。商业转载请联系官方受权,非商业转载请注明出处。get
初始思路:
刚开始的想法是想每一个字符开始向左右进行拓展,将所有的字符循环一遍,最后就能够找到最长的回文字符串。但本身感受这种方法时间复杂度过高了,就没往下想了,唉,太不自信了。
答案思路:
答案写的很是详细,分了三种方法,第三种不讲,有点复杂,首先要说的是和本身初始子路相似的解法-中心扩展算法,废话很少说,直接上代码:
class Solution { public: pair<int,int> getLongest(string & s,int left,int right) {
/*注意这里是while循环,会一直向外扩展,知道找到当前字符对应的最长回文串。*/ while(left>=0&&right<s.size()&&s[left]==s[right]) { left--; right++; }
/*对pair的用法不熟悉,还没想过能够这样用*/ return {left+1,right-1}; } string longestPalindrome(string s) { int start=0,end=0;
/*看这里,这个for循环,将每一个字符都进行遍历*/ for(int i=0;i<s.size();i++) {
/*感受很困惑吧,为啥要将getLongest函数调用两次,我简单的理解为奇数长度和偶数长度回文串两种状况。*/ auto [left1,right1]=getLongest(s,i,i); auto [left2,right2]=getLongest(s,i,i+1); if(right1-left1>end-start) { start=left1; end=right1; } if(right2-left2>end-start) { start=left2; end=right2; } }
/*返回最长的回文字符串,答案不惟一*/ return s.substr(start,end-start+1); } };
答案中介绍的第二种方法是动态规划,直接看代码:
class Solution {
public:
string longestPalindrome(string s) {
vector<vector<int>> dp(n, vector<int>(n));string strReturn="";
/*从长度1开始,一直到s.size(),注意不要被0误导*/
for(int len=0;len<s.size();len++)
{
/*每种长度下的字符都遍历一遍赋值*/
for(int i=0;i<s.size()-len;i++)
{
/*对应的是字符本身*/
if(len==0)
{
dp[i][i]=1;
}
/*长度1的状况*/
else if(len==1)
{
dp[i][i+len]=s[i]==s[i+len];
}
/*其余状况*/
else
{
dp[i][i+len]=dp[i+1][i+len-1]&&(s[i]==s[i+len]);
}
if(dp[i][i+len]&&len+1>strReturn.size())
{
strReturn=s.substr(i,len+1);
}
}
}
return strReturn;
}
};
两种算法的时间和空间复杂度对好比下:
时间复杂度 空间复杂度
中心扩展算法: O(n*n) O(1)
动态规划: O(n*n) O(n*n)