Problem#
You are given a palindromic string s
.
published: true
Return the lexicographically smallest palindromic permutation of s
.
Examples#
Example 1#
1
2
3
4
5
Input: s = "z"
Output: "z"
Explanation:
A string of only one character is already the lexicographically smallest
palindrome.
Example 2#
1
2
3
4
5
Input: s = "babab"
Output: "abbba"
Explanation:
Rearranging `"babab"` -> `"abbba"` gives the smallest lexicographic
palindrome.
Example 3#
1
2
3
4
5
Input: s = "daccad"
Output: "acddca"
Explanation:
Rearranging `"daccad"` -> `"acddca"` gives the smallest lexicographic
palindrome.
Constraints#
1 <= s.length <= 10^5
s
consists of lowercase English letters.
s
is guaranteed to be palindromic.
Method 1 – Greedy Character Placement#
Intuition#
To get the lexicographically smallest palindromic permutation, place the smallest available characters at the start and end, and the next smallest, and so on. If the length is odd, the center is the remaining odd-count character.
Approach#
Count the frequency of each character in s.
For each character in lex order, place half its count at the start and half at the end (mirrored).
If there is a character with an odd count, place it in the center.
Return the constructed palindrome.
Code#
Cpp
Java
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <string>
#include <vector>
using namespace std;
class Solution {
public :
string smallestPalindrome(string s) {
vector< int > cnt(26 );
for (char c : s) cnt[c- 'a' ]++ ;
string left = "" , mid = "" ;
for (int i = 0 ; i < 26 ; ++ i) {
if (cnt[i] % 2 ) mid += (char )('a' + i);
left += string(cnt[i]/ 2 , 'a' + i);
}
string right = left; reverse(right.begin(), right.end());
return left + mid + right;
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Solution {
public String smallestPalindrome (String s) {
int [] cnt = new int [ 26] ;
for (char c : s.toCharArray ()) cnt[ c- 'a' ]++ ;
StringBuilder left = new StringBuilder(), mid = new StringBuilder();
for (int i = 0; i < 26; ++ i) {
if (cnt[ i] % 2 == 1) mid.append ((char )('a' + i));
for (int j = 0; j < cnt[ i]/ 2; ++ j) left.append ((char )('a' + i));
}
String right = left.reverse ().toString ();
left.reverse ();
return left.toString () + mid.toString () + right;
}
}
1
2
3
4
5
6
7
8
9
10
class Solution :
def smallestPalindrome (self, s: str) -> str:
from collections import Counter
cnt = Counter(s)
left, mid = [], ''
for ch in sorted(cnt):
if cnt[ch] % 2 :
mid = ch
left. append(ch * (cnt[ch]// 2 ))
return '' . join(left) + mid + '' . join(left)[::- 1 ]
Complexity#
⏰ Time complexity: O(n)
, where n is the length of s. Each character is processed a constant number of times.
🧺 Space complexity: O(n)
, for the output string and counters.
Solution#
Method 1 -#
Code#
Complexity#
⏰ Time complexity: O(nnnxxxnnn)
🧺 Space complexity: O(nnnxxx)