1. 程式人生 > >【LeetCode】5. Longest Palindromic Substring(C++)

【LeetCode】5. Longest Palindromic Substring(C++)

題目:

Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.
Example 1:

Input: “babad”
Output: “bab”
Explanation: “aba” is also a valid answer.

Example 2:

Input: “cbbd”
Output: “bb”

理解:

本題要求尋找最長的迴文子串。
迴文子串有個很重要的性質,就是若一個串是迴文的,則給其兩側分別新增一個相同的字元,得到的仍然是迴文串。
有點可惜,有上面的思路,但是還是看了別人的才把具體實現寫出來。
因此,可以根據上面的性質,從每一個字元開始擴充套件。注意要把長度為奇數和偶數的分開來判斷。
複雜度:

  • 時間複雜度:O(n2)O(n^2)。遍歷一遍字串,每個位置要向兩邊擴充套件,因此是平方複雜度。
  • 空間複雜度:O(1)O(1)

實現1:

class Solution {
	int expandAroundCenter(const string& s, int l, int r) {
		while (l >= 0 && r < s.size() && s[l] == s[r]) {
			--l;
			++r;
		}
		return r - l - 1;
	}
public:
	string longestPalindrome(string s) {
		if (s.size() <= 1) return s;
		int lenMax = 0; int start = -1;
		for (int i = 0; i < s.size(); ++i) {
			int len1 = expandAroundCenter(s, i, i);
			int len2 = expandAroundCenter(s, i, i + 1);
			int len = max(len1, len2);
			if (len > lenMax) {
				start = i - (len - 1) / 2;
				lenMax = len;
			}
		}
		return s.substr(start, lenMax);
	}
};

還有另外一種實現,通過跳過重複字元,可以避免分奇偶的兩次判斷。

實現2:

注意全部字母相同的字串無論奇偶都是迴文串。
下面的實現巧妙的避開了分奇偶的判斷。先找到從j開始的重複單個字元子串,然後再向兩邊擴充套件即可。j為重複字元的開始,k為結束。

class Solution {
public:
	string longestPalindrome(string s) {
		if (s.empty()) return "";
		if (s.size() == 1) return s;
		int min_start = 0, max_len = 1;
		for (int i = 0; i < s.size();) {
			if (s.size() - i <= max_len / 2) break;
			int j = i, k = i;
			while (k < s.size() - 1 && s[k + 1] == s[k]) ++k; // Skip duplicate characters.
			i = k + 1;
			while (k < s.size() - 1 && j > 0 && s[k + 1] == s[j - 1]) { ++k; --j; } // Expand.
			int new_len = k - j + 1;
			if (new_len > max_len) { min_start = j; max_len = new_len; }
		}
		return s.substr(min_start, max_len);
	}
};

還有dp和另一種演算法,看完電影回來補。fantastic beasts, I’m coming.