grandyang / leetcode

Provide all my solutions and explanations in Chinese for all the Leetcode coding problems.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[LeetCode] 409. Longest Palindrome

grandyang opened this issue · comments

 

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

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

 

Example 1:

Input: s = "abccccdd"
Output: 7
Explanation: One longest palindrome that can be built is "dccaccd", whose length is 7.

Example 2:

Input: s = "a"
Output: 1
Explanation: The longest palindrome that can be built is "a", whose length is 1.

 

Constraints:

  • 1 <= s.length <= 2000
  • s consists of lowercase and/or uppercase English letters only.

 

这又是一道关于回文字符串的问题,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;
    }
};

 

上面那种方法是通过 HashMap 来建立字符串和其出现次数的映射,这里可以换一种思路,来找出所有奇数个的字符,这里采用的方法是使用一个 HashSet 集合,如果遍历到的字符不在 HashSet 中,那么就将其加入 HashSet,如果已经在 HashSet 里了,就将其从 HashSet 中删去,这样遍历完成后 HashSet 中就是所有出现个数是奇数个的字符了,那么最后只要用原字符串的长度减去0和 HashSet 长度减一之间的较大值即可,为啥这样呢,我们想一下,如果没有出现个数是奇数个的字符,那么 HashSet 的长度就是0,减1成了-1,那么原字符串的长度只要减去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);
    }
};

 

Github 同步地址:

#409

 

类似题目:

Palindrome Pairs

Palindrome Permutation II

Palindrome Permutation

Palindrome Linked List

Shortest Palindrome

Palindrome Partitioning II

Palindrome Partitioning

Valid Palindrome

Palindrome Number

Longest Palindromic Substring

 

参考资料:

https://leetcode.com/problems/longest-palindrome/

https://leetcode.com/problems/longest-palindrome/discuss/89604/Simple-HashSet-solution-Java

https://leetcode.com/problems/longest-palindrome/discuss/89587/What-are-the-odds-(Python-and-C%2B%2B)

 

LeetCode All in One 题目讲解汇总(持续更新中...)

(欢迎加入博主的知识星球,博主将及时答疑解惑,并分享刷题经验与总结,快快加入吧~)

知识星球 喜欢请点赞,疼爱请打赏❤️~.~

微信打赏

|

Venmo 打赏


---|---