Longest Palindrome
Length of the longest palindrome buildable from the input letters — count pairs.
3 min read
hash-map counting
Problem#
Given a string s of lowercase and uppercase letters, return the length of the longest palindrome that can be built using those letters. Letters are case-sensitive.
Examples#
"abccccdd"→7(e.g.,"dccaccd")."a"→1.
Constraints#
1 <= s.length <= 2000, letters only.
Hints#
Hint
Every letter contributes
count - (count % 2) characters; add 1 if any letter had an odd count. Approach#
Count each letter. Sum count - (count & 1) to get all paired letters. If any letter has odd count, add 1 to place a single middle character.
Solution#
class Solution {public: int longestPalindrome(string s) { int cnt[128] = {0}; for (char c : s) ++cnt[(unsigned char)c]; int total = 0; bool hasOdd = false; for (int i = 0; i < 128; ++i) { total += cnt[i] & ~1; // drop the low bit if (cnt[i] & 1) hasOdd = true; } return total + (hasOdd ? 1 : 0); }};func longestPalindrome(s string) int { var cnt [128]int for i := 0; i < len(s); i++ { cnt[s[i]]++ } total := 0 hasOdd := false for i := 0; i < 128; i++ { total += cnt[i] &^ 1 if cnt[i]&1 == 1 { hasOdd = true } } if hasOdd { total++ } return total}from collections import Counter
class Solution: def longestPalindrome(self, s: str) -> int: cnt = Counter(s) total = 0 has_odd = False for c in cnt.values(): total += c & ~1 if c & 1: has_odd = True return total + (1 if has_odd else 0)function longestPalindrome(s) { const cnt = new Map(); for (const c of s) cnt.set(c, (cnt.get(c) ?? 0) + 1); let total = 0; let hasOdd = false; for (const c of cnt.values()) { total += c & ~1; if (c & 1) hasOdd = true; } return total + (hasOdd ? 1 : 0);}class Solution { public int longestPalindrome(String s) { int[] cnt = new int[128]; for (int i = 0; i < s.length(); i++) cnt[s.charAt(i)]++; int total = 0; boolean hasOdd = false; for (int i = 0; i < 128; i++) { total += cnt[i] & ~1; if ((cnt[i] & 1) == 1) hasOdd = true; } return total + (hasOdd ? 1 : 0); }}function longestPalindrome(s: string): number { const cnt = new Map<string, number>(); for (const c of s) cnt.set(c, (cnt.get(c) ?? 0) + 1); let total = 0; let hasOdd = false; for (const c of cnt.values()) { total += c & ~1; if (c & 1) hasOdd = true; } return total + (hasOdd ? 1 : 0);}Editorial#
A palindrome can use any letter in pairs (one on each side of center) plus at most one odd letter in the middle. Bit-trick cnt & ~1 strips the low bit, leaving the pairable count. hasOdd is a single boolean — multiple odd letters still give only one center slot.
Complexity#
- Time: O(N).
- Space: O(1).
Concept revision#
Related#