Smallest Palindromic Rearrangement I

Med
#3129Time: O(N * N!), where N is the length of the string. Generating all permutations is factorial in time, and for each permutation, we do an O(N) check. This is prohibitively slow.Space: O(N), for the recursion stack depth and the `StringBuilder` used to build permutations.
Data structures

Prompt

You are given a palindromic string s.

Return the lexicographically smallest palindromic permutation of s.

 

Example 1:

Input: s = "z"

Output: "z"

Explanation:

A string of only one character is already the lexicographically smallest palindrome.

Example 2:

Input: s = "babab"

Output: "abbba"

Explanation:

Rearranging "babab""abbba" gives the smallest lexicographic palindrome.

Example 3:

Input: s = "daccad"

Output: "acddca"

Explanation:

Rearranging "daccad""acddca" gives the smallest lexicographic palindrome.

 

Constraints:

  • 1 <= s.length <= 105
  • s consists of lowercase English letters.
  • s is guaranteed to be palindromic.

Approaches

2 approaches with complexity analysis and trade-offs.

This is a naive approach that explores all possible rearrangements of the characters in the input string s. For each rearrangement (permutation), it checks if the new string is a palindrome. It keeps track of the lexicographically smallest palindrome found among all valid permutations.

Algorithm

  • Count the frequency of each character in the input string s.
  • Define a recursive backtracking function, generate(current_permutation, character_counts).
  • Base Case: If the length of current_permutation equals the length of s:
    • Check if current_permutation is a palindrome.
    • If it is, compare it with the smallest palindrome found so far and update if the current one is smaller.
    • Return.
  • Recursive Step: Iterate through all possible characters ('a' to 'z').
    • If a character's count is greater than zero:
      • Decrement its count.
      • Append the character to current_permutation.
      • Make a recursive call: generate(current_permutation, character_counts).
      • Backtrack: Remove the last character from current_permutation and restore the character's count.
  • Initialize the process by calling the function with an empty permutation.
  • The smallest palindrome found after exploring all possibilities is the answer.

Walkthrough

The algorithm first needs a way to generate all unique permutations of the characters of s. This is typically done using a recursive backtracking function. The function would explore placing each available character at the current position in the permutation being built. To handle duplicate characters, we can use a frequency map of characters. Once a full permutation of length n is generated, we check if it's a palindrome. A string is a palindrome if it reads the same forwards and backwards. We maintain a variable, say smallestPalindrome, initialized to a lexicographically large value. Whenever we find a new palindrome, we compare it with smallestPalindrome and update it if the new one is smaller. After checking all possible permutations, smallestPalindrome will hold the answer. Given the constraints (s.length <= 10^5), this approach is computationally infeasible.

// Note: This code is for demonstration and will cause a Time Limit Exceeded error.class Solution {    String smallestPalindrome = null;     public String makeSmallestPalindrome(String s) {        int[] counts = new int[26];        for (char c : s.toCharArray()) {            counts[c - 'a']++;        }        generatePermutations(new StringBuilder(), counts, s.length());        return smallestPalindrome;    }     private void generatePermutations(StringBuilder current, int[] counts, int n) {        if (current.length() == n) {            String perm = current.toString();            if (isPalindrome(perm)) {                if (smallestPalindrome == null || perm.compareTo(smallestPalindrome) < 0) {                    smallestPalindrome = perm;                }            }            return;        }         for (int i = 0; i < 26; i++) {            if (counts[i] > 0) {                counts[i]--;                current.append((char) ('a' + i));                generatePermutations(current, counts, n);                // Backtrack                current.deleteCharAt(current.length() - 1);                counts[i]++;            }        }    }     private boolean isPalindrome(String str) {        int left = 0;        int right = str.length() - 1;        while (left < right) {            if (str.charAt(left) != str.charAt(right)) {                return false;            }            left++;            right--;        }        return true;    }}

Complexity

Time

O(N * N!), where N is the length of the string. Generating all permutations is factorial in time, and for each permutation, we do an O(N) check. This is prohibitively slow.

Space

O(N), for the recursion stack depth and the `StringBuilder` used to build permutations.

Trade-offs

Pros

  • It's a straightforward, brute-force method that correctly solves the problem for very small inputs.

Cons

  • Extremely inefficient and will not pass for the given constraints.

  • The number of permutations grows factorially with the length of the string, making it infeasible for n > 15.

Video walkthrough

Newsletter

One sharp idea, every week

System design and interview prep — short enough to finish.

No spam. Unsubscribe anytime.

Practice

Same difficulty — related problems to reinforce the pattern.