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.
这又是一道关于回文字符串的问题,LeetCode上关于回文串的题有十来道呢,也算一个比较重要的知识点。但是这道题确实不算一道难题,给了我们一个字符串,让我们找出可以组成的最长的回文串的长度,由于字符顺序可以打乱,所以问题就转化为了求偶数个字符的个数,我们了解回文串的都知道,回文串主要有两种形式,一个是左右完全对称的,比如noon, 还有一种是以中间字符为中心,左右对称,比如bob,level等,那么我们统计出来所有偶数个字符的出现总和,然后如果有奇数个字符的话,我们取取出其最大偶数,然后最后结果加1即可,参见代码如下:
解法一:
class Solution { public: int longestPalindrome(string s) { int res = 0; bool mid = false; unordered_map<char, int> m; for (char c : s) ++m[c]; for (auto it = m.begin(); it != m.end(); ++it) { res += it->second; if (it->second % 2 == 1) { res -= 1; mid = true; } } return mid ? res + 1 : res; } };
上面那种方法是通过哈希表来建立字符串和其出现次数的映射,这里我们可以换一种思路,来找出搜有奇数个的字符,我们采用的方法是使用一个set集合,如果遍历到的字符不在set中,那么就将其加入set,如果已经在set里了,就将其从set中删去,这样遍历完成后set中就是所有出现个数是奇数个的字符了,那么我们最后只要用s的长度减去0和set长度减一之间的较大值即可,为啥这样呢,我们想,如果没有出现个数是奇数个的字符,那么t的长度就是0,减1成了-1,那么s的长度只要减去0即可;如果有奇数个的字符,那么字符个数减1,就是不能组成回文串的字符,因为回文串最多允许一个不成对出现的字符,参见代码如下:
解法二:
class Solution { public: int longestPalindrome(string s) { unordered_set<char> t; for (char c : s) { if (!t.count(c)) t.insert(c); else t.erase(c); } return s.size() - max(0, (int)t.size() - 1); } };
最后这种方法利用到了STL中的count函数,就是找字符串中某个字符出现的个数,那么我们和1相与,就可以知道该个数是奇数还是偶数了,返回的写法和上面那种方法相同,参见代码如下:
解法三:
class Solution { public: int longestPalindrome(string s) { int odds = 0; for (char c = 'A'; c <= 'z'; ++c) { odds += count(s.begin(), s.end(), c) & 1; } return s.size() - max(0, odds - 1); } };
类似题目:
参考资料:
https://discuss.leetcode.com/topic/61338/what-are-the-odds-python-c
https://discuss.leetcode.com/topic/61574/very-easy-to-understand-java-solution