↓Skip to main content
  1. LeetCode/

LeetCode 3518: Smallest Palindromic Rearrangement II

·3 mins· ·
LeetCode Hard Math Combinatorics Counting Hash-Table String
Wei Yi Chung
Author
Wei Yi Chung
Working at the contributing of open source, distributed systems, and data engineering.
Table of Contents

Meta Data
#

Difficulty: hard First Attempt: 2025-04-13

  • Submissions: WA → TLE ×2 (2025-04) → WA → TLE → RE → TLE → AC → RE → AC (2026-09-26)

Approach
#

s is a palindrome, so every character count is even except at most one. A palindrome is determined by its left half (the right half mirrors it, and the middle is the odd-count character), so the task becomes: the k-th permutation of the left half’s multiset.

Decide position by position:

  • Remaining permutations = remaining length! / Π remaining count of each character!.
  • Try character c here (smallest first): placing it leaves current count × cnt[c] / remaining length permutations.
    • If k falls in this branch (k <= that), place c and move on.
    • Otherwise subtract it from k and try the next character.
  • If the total is < k from the start, return the empty string.

My Attempts
#

WhenVersionProblem
2025-04WAComputed one next permutation and ignored k. For s = "cc", k = 6 there is only one palindromic arrangement, so the answer is empty; it returned "cc"
2025-04Two TLEsRan next permutation k - 1 times; k up to 10^6 is too slow
2026-09WASwitched to position-by-position, but the middle character only considered “characters with count < 2”, so a character appearing 3 times never became the middle. For s = "ccc", k = 1 the answer is "ccc"; it returned "cc"
2026-09TLE ×2Recomputed big-integer factorial divisions for every character tried
2026-09RE ×2Renamed the method to kthSmallestPalindrome, so LeetCode could not find smallestPalindrome
2026-09ACUpdated the permutation count in O(1): branch = current × cnt[c] // length

Solution
#

from math import factorial

class Solution:
    def smallestPalindrome(self, s: str, k: int) -> str:
        cnt = [0] * 26
        for ch in s:
            cnt[ord(ch) - 97] += 1
        mid = ""
        for i in range(26):
            if cnt[i] % 2:
                mid = chr(i + 97)                  # the odd-count character (3, 5, ... times too)
            cnt[i] //= 2                           # counts in the left half

        length = sum(cnt)
        ways = factorial(length)
        for c in cnt:
            ways //= factorial(c)
        if ways < k:
            return ""

        left = []
        for _ in range(length):
            for i in range(26):
                if cnt[i] == 0:
                    continue
                branch = ways * cnt[i] // length   # permutations after placing i here
                if k <= branch:
                    left.append(chr(i + 97))
                    cnt[i] -= 1
                    ways, length = branch, length - 1
                    break
                k -= branch
        half = "".join(left)
        return half + mid + half[::-1]

Complexity
#

O(26 · n) big-integer operations (plus the initial factorials), space O(n). Capping counts at k while computing them avoids big integers altogether.

Mistakes to Avoid
#

  • The middle character is the one with an odd count, not the one appearing once.
  • Enumerating permutations one by one: too slow for large k.
  • Recomputing factorials each time: update by the ratio cnt[c] / length.

Interview Explanation
#

A palindrome is fixed by its left half, so this is the k-th permutation of the left half’s multiset. I decide positions one at a time: placing character c leaves the current count times cnt[c] divided by the remaining length, so if k is within that I place c, otherwise I subtract and try the next. The middle is the odd-count character. Time O(26n).

Related

LeetCode 1814: Count Nice Pairs in an Array
·1 min
LeetCode Medium Array Hash-Table Math Counting
LeetCode 1814 note: rearrange the condition into nums[i] - rev(nums[i]) == nums[j] - rev(nums[j]), count pairs per value, and remember the modulus
LeetCode 1189: Maximum Number of Balloons
·2 mins
LeetCode Easy Hash-Table String Counting
LeetCode 1189 note: each letter supports count // needed balloons, with l and o needed twice; take the minimum
LeetCode 914: X of a Kind in a Deck of Cards
·2 mins
LeetCode Easy Array Hash-Table Math Counting
LeetCode 914 note: every card count must be divisible by one X >= 2, i.e. the GCD of all counts is at least 2
LeetCode 884: Uncommon Words from Two Sentences
·1 min
LeetCode Easy Hash-Table String Counting
LeetCode 884 note: count words across both sentences together; those appearing exactly once are the answer
LeetCode 819: Most Common Word
·2 mins
LeetCode Easy Array Hash-Table String Counting
LeetCode 819 note: replace punctuation with spaces, lowercase, split, count, and pick the most frequent word not banned
LeetCode 383: Ransom Note
·1 min
LeetCode Easy Hash-Table String Counting
LeetCode 383 note: every character’s demand in ransomNote must not exceed its supply in magazine; an empty Counter difference means yes