求最长回文子串。
解法1:直接暴力求解,两个函数,一个函数列出所有子串,一个函数判断是否回文串(遍历)。
但是时间复杂度太高,O(n3),只能通过一半的测试用例。
解法2:将字符串反转得到反转字符串rev,两个字符串相等,即为回文子串。按照这样的思路,主要还是两部分功能,一是列出所有子串,二是利用反转,判断是否回文串,时间复杂度O(n2)。
测试用例:102/103
class Solution { public://先找最长公共子串,再判断该子串是否是回文串 string longestPalindrome(string s) { if(s.length()==1) return s; string rev = s; string res; std::reverse(rev.begin(),rev.end()); if(rev==s) return s; int len = 0; for(int i = 0; i<s.length();i++){ string temp; for(int j = i; j < s.length();j++){ temp = temp+s[j]; if(len>=temp.length()) continue; else if(rev.find(temp)!=-1){ string q = temp; std::reverse(q.begin(),q.end()); if(q==temp){ len = temp.length(); res = temp; } } else break; } temp = ""; } return res; } };
解法3:中心扩展法
以"ababd"为例,最大回文子串为"bab",该子串可以看成是由“a”为中心扩展开来的;而“dbaabc”这种,则是由aa扩展开来的,因此,假设字符串长度为n,中心点为1的话(n种可能),中心点为2的话(n-1种可能),因此最多有(2n-1)个中心。时间复杂度O(n2)。
class Solution { public: string longestPalindrome(string s) { if(s.length() < 1){ return ""; } int start = 0, end = 0; for(int i = 0;i<s.length();i++){ int len1 = expandAroundCenter(s, i , i); int len2 = expandAroundCenter(s, i, i + 1); // int len = max(len1, len2); if(len1 > end - start){ start = i - len1 / 2; end = i + len1 / 2; } if(len2 > end - start){ start = i - (len2 - 2) /2; end = i + 1 + (len2 -2) / 2; } } return s.substr(start, end - start + 1); } int expandAroundCenter(string s, int left, int right){ int L =left, R = right; while(L>=0 && R < s.length() && s[L] == s[R]){ L--; R++; } return R - L - 1; } };
解法4:动态规划算法
动态规划:由状态和状态转移构成
维护一个二维数组dp[j][i],i-j表示一个字符区间,true和false表示是否回文串。如果i == j,说明只有一个字符,是回文串;若j + 1 =i,说明两个字符,判断s[i]==s[j]即可;若i - 1 > j,说明至少有3个字符,除了需要判断s[i]和s[j]之外,需要判断s[i -1] == s[j + 1],因此,可以写出一个分段函数。
时间复杂度O(n2)
注意条件:若i - j < 2, 即i - j == 1或 i < j,则为1个字符或者没有,字符,直接满足条件
class Solution { public: string longestPalindrome(string s) { if (s.empty()) return ""; int n = s.size(), dp[n][n] = {0}, left = 0, len = 1; for (int i = 0; i < n; ++i) { dp[i][i] = 1; 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; } } } return s.substr(left, len); } };