思路
方法一:暴力法,双重循环判断
1 class Solution { 2 public: 3 //暴力法,时间复杂度O(n^2),提交之后会超时,不能accept 4 string longestPalindrome(string s) { 5 int slen = s.length(); 6 string maxPalindrome(1, s[0]); 7 for(int i = 0; i <= slen-2; ++i) { 8 for(int j = i+1; j <= slen-1; ++j) { 9 if(s[i] == s[j] && isPalindrome(s, i, j)) { 10 if(j-i+1 > maxPalindrome.length()) 11 maxPalindrome = s.substr(i, j-i+1); 12 } 13 } 14 } 15 16 return maxPalindrome; 17 } 18 19 //判断回文串 20 bool isPalindrome(const string& s, int i, int j) { 21 while(i < j) { 22 if(s[i] != s[j]) { 23 return false; 24 } 25 26 ++i; 27 --j; 28 } 29 30 return true; 31 } 32 };
复杂度分析:
时间复杂度:O(n3),双重循环嵌套一个判断回文串的函数,双重循环是O(n2),判断回文串是O(n)。
方法二:动态规划
1 class Solution { 2 public: 3 string longestPalindrome(string s) { 4 int slen = s.length(); 5 string maxPalindrome(1, s[0]); //初始化为第一个字符 6 vector<vector<bool>> dp(slen, vector<bool>(slen, false)); 7 8 for(int len = 0; len < slen; ++len) { 9 for(int i = 0; i + len < slen; ++i) { 10 int j = i+len; 11 if(j-i == 0) { 12 dp[i][j] = true; 13 } else if(j-i == 1) { 14 dp[i][j] = (s[i] == s[j]); 15 } else { 16 dp[i][j] = (s[i] == s[j] && dp[i+1][j-1]); 17 } 18 19 if(dp[i][j] && j-i+1 > maxPalindrome.length()) { 20 maxPalindrome = s.substr(i, j-i+1); 21 } 22 } 23 } 24 25 26 return maxPalindrome; 27 } 28 };
方法三:中心扩展算法
1 class Solution { 2 public: 3 string longestPalindrome(string s) { 4 int start = 0, end = 0; 5 for (int i = 0; i < s.length(); i++) { 6 int len1 = expandAroundCenter(s, i, i); 7 int len2 = expandAroundCenter(s, i, i + 1); 8 int len = max(len1, len2); 9 if (len > end - start) { 10 start = i - (len - 1) / 2; 11 end = i + len / 2; 12 } 13 } 14 return s.substr(start, end - start + 1); 15 } 16 17 int expandAroundCenter(const string& s, int left, int right) { 18 while (left >= 0 && right < s.length() && s[left] == s[right]) { 19 --left; 20 ++right; 21 } 22 return right - left - 1; 23 } 24 };
方法四:Manacher 算法 (马拉车算法)
还有一个复杂度为 O(n)Manacher 算法。然而本算法十分复杂,一般不作为面试内容。这里给出,仅供有兴趣的同学挑战自己。
参考
本文转载自:LeetCode官方题解 - 最长回文子串