[LeetCode]409. Longest Palindrome 解題報告

Given a string which consists of lowercase or uppercase letters, find the length of the longest palindromes that can be built with those letters.

This is case sensitive, for example "Aa" is not considered a palindrome here.

Note:
Assume the length of given string will not exceed 1,010.

Example:

Input:
"abccccdd"

Output:
7

Explanation:
One longest palindrome that can be built is "dccaccd", whose length is 7.

這個題屬於easy難度,確實比較容易。其實這題跟Palindrome沒什麼關係,分析以後會發現,Palindrome肯定是成對成對出現的,所以,找出所有成對的字母即可,如果剩下單個的字母,那麼可以放在最中間,最後的長度加一,否則不加。

具體來說,先把String轉換爲char[],直接操作數組總是最快的。先從頭開始遍歷整個字符串,找到和第一個字母一樣的字母,計數,當前字母數量/2*2,就當前字母的有效長度。如果統計過的字母,可以作一個標記,比如“*”,這樣下次就可以不統計了。接下來統計第二個字母,如果這個字母爲*,就不統計了。以此類推,直到最後一個。

另外,需要一個boolean型變量,來記住是否有單獨出來的字母,字母數量%2,就知道了,然後將boolean設爲true,在返回值的時候判斷這個變量是不是true就好了。

儘管對於統計過的字母作了標記,但是這種標記只是爲了不重複統計相同的字母,並不會減少遍歷的次數,所以這種方法的時間複雜度仍然爲O(n^2)

代碼如下:

public class Solution {
	public int longestPalindrome(String s) {
		int nLongestLength = 0;
		boolean bAlone = false;
		char[] cArr = s.toCharArray();
		int nIndex = 0;
		while (nIndex < cArr.length) {
			int nCurrentNum = 0;
			char cLast = cArr[nIndex];
			for (int i = 0; i < cArr.length; i++) {
				if (cLast == cArr[i]) {
					nCurrentNum++;
					cArr[i] = '*';
				}
				while (i + 1 < cArr.length && cArr[i + 1] == '*') {
					i++;
				}
			}
			nLongestLength += (nCurrentNum / 2) * 2;
			bAlone = (!bAlone && nCurrentNum % 2 == 1) ? true : bAlone;
			while (nIndex + 1 < cArr.length && cArr[nIndex + 1] == '*') {
				nIndex++;
			}
			nIndex++;
		}
		return bAlone ? nLongestLength + 1 : nLongestLength;
	}
}

接下來,對於數組,我們可以使用LinkedList來處理,使用list.remove來代替“*”的處理,如果統計過了,直接從list裏面去掉即可。但是這種方法性能非常差,我個人認爲性能瓶頸可能在Linkedlist的構造和操作上。因此,提交代碼的時候建議儘量使用數組。
public class Solution {
	public int longestPalindrome(String s) {
		int nLongestLength = 0;
		boolean bAlone = false;
		char[] cArr = s.toCharArray();
		List<Character> listChar = new LinkedList<>();
		for (Character character : cArr) {
			listChar.add(character);
		}
		while (listChar.size() > 0) {
			int nCurrentNum = 0;
			char cLast = listChar.get(0);
			for (int i = 0; i < listChar.size(); i++) {
				if (cLast == listChar.get(i)) {
					nCurrentNum++;
					listChar.remove(i);
					i--;
				}
			}
			nLongestLength += (nCurrentNum / 2) * 2;
			bAlone = (!bAlone && nCurrentNum % 2 == 1) ? true : bAlone;
		}
		return bAlone ? nLongestLength + 1 : nLongestLength;
	}
}

第一種方式大約打敗了60%,第二種方式打敗了0.5%。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章