Menu
DSA interview questionsQuestion 25 of 249

DSA interview question · Question 25 of 249

Longest Palindrome: Pair Up Letter Counts and Keep One Centre

  • Easy
  • coding
  • ~8 min
  • Medium relevance
  • 4 min read
  • Updated Oct 2026

Short answer

A palindrome mirrors around its centre, so every letter except possibly one must be used an even number of times. Count each letter; each count c contributes c // 2 * 2 letters as mirrored pairs. If any count was odd, one spare letter can sit in the middle, so add 1. That is O(n) time and O(1) space for a fixed alphabet. A neat equivalent: the answer is n minus the number of odd counts, plus 1 if there was at least one odd count. Letters are case-sensitive.

On this page
  1. Problem
  2. Examples
  3. Approach 1: brute force
  4. Approach 2: optimal (counting pairs)
  5. Tests
  6. Edge cases and pitfalls
  7. Where this shows up in data engineering

Problem

You are given a string s of upper- and lowercase English letters. Using any subset of its letters, each letter at most as many times as it appears, you want to arrange a palindrome. Return the length of the longest one possible. Upper and lower case count as different letters. This is LeetCode 409, Longest Palindrome.

You only return the length, and the order of s does not matter.

Examples

s = "aabbbcd"     ->  5    (e.g. "abbba": pairs a, a, b, b plus a spare b in the middle)
s = "Aa"          ->  1    ("A" and "a" are different letters)
s = "zzzz"        ->  4
s = "x"           ->  1

Approach 1: brute force

Try every multiset of letters, from largest to smallest, and test whether it can be arranged into a palindrome. A multiset can form a palindrome when at most one letter has an odd count. Enumerating subsets is exponential, so this only works for tiny inputs, but it is a useful oracle for testing.

from collections import Counter
from itertools import combinations

def longest_palindrome_brute(s):
    for size in range(len(s), 0, -1):
        for picked in combinations(s, size):
            odd = sum(c % 2 for c in Counter(picked).values())
            if odd <= 1:
                return size
    return 0

Complexity: O(2^n · n) time in the worst case. Only for checking the real solution on short strings.

Approach 2: optimal (counting pairs)

Key insight: a palindrome reads the same from both ends, so letters come in mirrored pairs. The only exception is the single middle position of an odd-length palindrome. So use as many pairs of each letter as you can, then, if any letter had a leftover, spend one leftover on the middle.

from collections import Counter

def longest_palindrome(s):
    length = 0
    has_odd = False
    for c in Counter(s).values():
        length += c // 2 * 2
        if c % 2:
            has_odd = True
    return length + (1 if has_odd else 0)

On "aabbbcd" the counts are a:2, b:3, c:1, d:1. Pairs give 2 + 2 + 0 + 0 = 4 letters, some count is odd, so the answer is 5.

The same idea as a one-liner: every odd count wastes exactly one letter, except that one of them can be the centre.

def longest_palindrome_odds(s):
    odd = sum(c % 2 for c in Counter(s).values())
    return len(s) - odd + (1 if odd else 0)

Why it is correct: no palindrome can use more than c // 2 * 2 copies of a letter in mirrored positions, and it has at most one unmirrored position. The greedy choice reaches both limits at once, so nothing longer exists.

Complexity: O(n) time, O(k) space for an alphabet of k letters (at most 52 here, so O(1)).

Tests

import random

for f in (longest_palindrome, longest_palindrome_odds, longest_palindrome_brute):
    assert f("aabbbcd") == 5
    assert f("Aa") == 1                 # case-sensitive
    assert f("zzzz") == 4               # all pairs, no centre needed
    assert f("x") == 1
    assert f("abc") == 1                # only a centre
    assert f("aaabbbccc") == 7          # three odd counts, one becomes the centre

assert longest_palindrome("") == 0      # defensive

random.seed(4)
for _ in range(300):
    s = "".join(random.choice("abAB") for _ in range(random.randint(1, 8)))
    assert longest_palindrome(s) == longest_palindrome_odds(s) == longest_palindrome_brute(s)

Edge cases and pitfalls

  • Add the centre at most once, not once per odd letter. "aaabbbccc" gives 7, not 9.
  • An odd count still contributes its pairs: three bs give two mirrored bs plus a candidate centre. Skipping odd counts entirely is a common mistake.
  • Do not lowercase the input; the problem treats "A" and "a" as different.
  • This is about rearranging letters. It is unrelated to the longest palindromic substring, which keeps the original order.

Where this shows up in data engineering

The pattern is “aggregate counts, then reason about parity”, which is a GROUP BY followed by a small calculation over the counts. Parity checks on counts are also a cheap sanity check in pipelines, for example confirming that every opening event has a matching closing event.

By DataDank Editorial · Last reviewed Oct 2026 · Python 3 solutions verified with assert-based tests

Progress is saved in this browser only. No account needed.

Search
Filter by type