題目
給定一個包含大寫字母和小寫字母的字符串,找到通過這些字母構造成的最長的迴文串。
在構造過程中,請注意區分大小寫。比如 “Aa” 不能當做一個迴文字符串。
注意:
假設字符串的長度不會超過 1010。
示例 1:
輸入:
“abccccdd”
輸出:
7
解釋:
我們可以構造的最長的迴文串是"dccaccd", 它的長度是 7。
解法一(字典)
思路:可以構建迴文串就相當於構建左右對稱的字符,但是最中間可以出現一個字符,因此對於奇數可以進行多一個字符。
即題目的思路就是統計字符中可以構建最多的偶數個數,如果是奇數則減一即爲最大的偶數,如果是偶數則本身即爲最大的偶數。
- 統計每個字符的個數
- 對字符個數進行奇偶判斷,偶數直接累加,奇數標記並減一後累加
- 如果出現過奇數,則整體加1
- 時間複雜度:O(n)
- 空間複雜度:O(n)
public class Solution {
//[email protected]
public int LongestPalindrome(string s) {
int cnt = 0;
Dictionary<char,int> dict = new Dictionary<char,int>();
foreach(char item in s)
{//統計每個字符個數
if(dict.ContainsKey(item))
{
dict[item] ++;
}
else
{
dict.Add(item,1);
}
}
bool flag = false;
foreach(int item in dict.Values)
{
if((item & 1) == 1)
{//奇數
cnt += item - 1;
flag = true;
}
else
{//偶數
cnt += item;
}
}
cnt += flag?1:0;
return cnt;
}
}
解法二(固定數組)
思路:前面解法是最常規或者第一反應的做法,現在使用固定數組保存字符個數,減少字典hash的計算,儘管消耗也不大。
- 申請固定長度數組:58 = ‘z’ - ‘A’ + 1,或者可以直接申請128(ascii)個,則不用進行減’A’的計算
- 統計字符個數,利用了除法取整進行了奇數過濾,即3/2 ==(int)1.5 == 1
- 本解法判斷奇數方法跟前面不同,是通過整體字符長度大於當前求和長度來判斷。
- 時間複雜度:O(n)
- 空間複雜度:O(1)
public class Solution {
//[email protected]
public int LongestPalindrome(string s) {
int cnt = 0;
int [] arrChar = new int[58];
foreach(char item in s)
{//統計每個字符個數
arrChar[item - 'A'] ++;
}
foreach(int item in arrChar)
{//字符計數
cnt += (int)(item / 2) * 2;
}
cnt += cnt < s.Length?1:0;
return cnt;
}
}
解法三(Pythonic)
思路:用Python的內置函數進行運算來簡化程序
- 使用collections.Counter函數,對每個字符出現次數進行統計
- 使用sum函數,對所有次數裏的偶數求和
- 如果有奇數存在,則整體加1
class Solution:
#[email protected]
def longestPalindrome(self, s: str) -> int:
cnt = sum([v-1 if v%2==1 else v for v in collections.Counter(s).values()])
return cnt + 1 if cnt < len(s) else cnt
截圖從上往下分別是:解法2,1,3
解法2執行出錯,是開始申請的空間是26,忽略了大小寫