Welcome to Subscribe On Youtube
3518. Smallest Palindromic Rearrangement II
Description
You are given a palindromic string s and an integer k.
Return the k-th lexicographically smallest palindromic permutation of s. If there are fewer than k distinct palindromic permutations, return an empty string.
Note: Different rearrangements that yield the same palindromic string are considered identical and are counted once.
Example 1:
Input: s = "abba", k = 2
Output: "baab"
Explanation:
- The two distinct palindromic rearrangements of
"abba"are"abba"and"baab". - Lexicographically,
"abba"comes before"baab". Sincek = 2, the output is"baab".
Example 2:
Input: s = "aa", k = 2
Output: ""
Explanation:
- There is only one palindromic rearrangement:
"aa". - The output is an empty string since
k = 2exceeds the number of possible rearrangements.
Example 3:
Input: s = "bacab", k = 1
Output: "abcba"
Explanation:
- The two distinct palindromic rearrangements of
"bacab"are"abcba"and"bacab". - Lexicographically,
"abcba"comes before"bacab". Sincek = 1, the output is"abcba".
Constraints:
1 <= s.length <= 104sconsists of lowercase English letters.sis guaranteed to be palindromic.1 <= k <= 106
Solutions
Solution 1
-
impl Solution { pub fn smallest_palindrome(s: String, k: i32) -> String { let bytes = s.as_bytes(); let rank = k.max(1) as usize; const COUNT_LIMIT: usize = 1_000_001; let mut frequencies = [0usize; 26]; for &byte in bytes { frequencies[(byte - b'a') as usize] += 1; } let mut odd_count = 0usize; let mut middle_char_index = 26u8; for char_index in 0..26 { if frequencies[char_index] & 1 == 1 { odd_count += 1; middle_char_index = char_index as u8; } } if odd_count > 1 { return String::new(); } let mut half_frequencies = [0usize; 26]; let mut half_length = 0usize; for char_index in 0..26 { half_frequencies[char_index] = frequencies[char_index] / 2; half_length += half_frequencies[char_index]; } let count_permutations = |counts: &[usize; 26]| -> usize { let mut remaining: usize = counts.iter().sum(); let mut permutations = 1usize; for &count in counts { if count == 0 { continue; } let selected = count.min(remaining - count); let mut combinations = 1usize; for step in 1..=selected { combinations = combinations * (remaining - step + 1) / step; if combinations >= COUNT_LIMIT { combinations = COUNT_LIMIT; break; } } permutations *= combinations; if permutations >= COUNT_LIMIT { return COUNT_LIMIT; } remaining -= count; } permutations }; if rank > count_permutations(&half_frequencies) { return String::new(); } let length = bytes.len(); let mut palindrome = vec![0u8; length]; let mut remaining_rank = rank; let mut position = 0usize; for _ in 0..half_length { for char_index in 0..26 { if half_frequencies[char_index] == 0 { continue; } half_frequencies[char_index] -= 1; let suffix_count = count_permutations(&half_frequencies); if suffix_count >= remaining_rank { palindrome[position] = char_index as u8 + b'a'; position += 1; break; } remaining_rank -= suffix_count; half_frequencies[char_index] += 1; } } if middle_char_index < 26 { palindrome[half_length] = middle_char_index + b'a'; } for index in 0..half_length { palindrome[length - 1 - index] = palindrome[index]; } String::from_utf8(palindrome).unwrap() } } -
class Solution { private static final int LIMIT = 1_000_001; public String smallestPalindrome(String s, int k) { int[] freq = new int[26]; int n = s.length(); for (int i = 0; i < n; ++i) { ++freq[s.charAt(i) - 'a']; } int odd = 0; int mid = 26; for (int i = 0; i < 26; ++i) { if ((freq[i] & 1) == 1) { ++odd; mid = i; } } if (odd > 1) { return ""; } int[] half = new int[26]; int halfLen = 0; for (int i = 0; i < 26; ++i) { half[i] = freq[i] / 2; halfLen += half[i]; } if (k > countPermutations(half)) { return ""; } char[] pal = new char[n]; int rank = k; int pos = 0; for (int t = 0; t < halfLen; ++t) { for (int i = 0; i < 26; ++i) { if (half[i] == 0) { continue; } --half[i]; int suffix = countPermutations(half); if (suffix >= rank) { pal[pos++] = (char) ('a' + i); break; } rank -= suffix; ++half[i]; } } if (mid < 26) { pal[halfLen] = (char) ('a' + mid); } for (int i = 0; i < halfLen; ++i) { pal[n - 1 - i] = pal[i]; } return new String(pal); } private int countPermutations(int[] counts) { int remaining = 0; for (int c : counts) { remaining += c; } long perms = 1; for (int count : counts) { if (count == 0) { continue; } int selected = Math.min(count, remaining - count); long combos = 1; for (int step = 1; step <= selected; ++step) { combos = combos * (remaining - step + 1) / step; if (combos >= LIMIT) { combos = LIMIT; break; } } perms *= combos; if (perms >= LIMIT) { return LIMIT; } remaining -= count; } return (int) perms; } } -
class Solution { public: string smallestPalindrome(string s, int k) { int freq[26]{}; int n = s.size(); for (char c : s) { ++freq[c - 'a']; } int odd = 0, mid = 26; for (int i = 0; i < 26; ++i) { if (freq[i] & 1) { ++odd; mid = i; } } if (odd > 1) { return ""; } int half[26]{}; int halfLen = 0; for (int i = 0; i < 26; ++i) { half[i] = freq[i] / 2; halfLen += half[i]; } if (k > countPermutations(half)) { return ""; } string pal(n, 0); int rank = k, pos = 0; for (int t = 0; t < halfLen; ++t) { for (int i = 0; i < 26; ++i) { if (half[i] == 0) { continue; } --half[i]; int suffix = countPermutations(half); if (suffix >= rank) { pal[pos++] = char('a' + i); break; } rank -= suffix; ++half[i]; } } if (mid < 26) { pal[halfLen] = char('a' + mid); } for (int i = 0; i < halfLen; ++i) { pal[n - 1 - i] = pal[i]; } return pal; } private: static constexpr int LIMIT = 1000001; int countPermutations(const int counts[26]) { int remaining = 0; for (int i = 0; i < 26; ++i) { remaining += counts[i]; } long long perms = 1; for (int i = 0; i < 26; ++i) { int count = counts[i]; if (count == 0) { continue; } int selected = min(count, remaining - count); long long combos = 1; for (int step = 1; step <= selected; ++step) { combos = combos * (remaining - step + 1) / step; if (combos >= LIMIT) { combos = LIMIT; break; } } perms *= combos; if (perms >= LIMIT) { return LIMIT; } remaining -= count; } return (int) perms; } }; -
class Solution: def smallestPalindrome(self, s: str, k: int) -> str: limit = 1_000_001 freq = [0] * 26 for ch in s: freq[ord(ch) - 97] += 1 odd = 0 mid = 26 for i, v in enumerate(freq): if v & 1: odd += 1 mid = i if odd > 1: return "" half = [v // 2 for v in freq] half_len = sum(half) def count_permutations(counts: List[int]) -> int: remaining = sum(counts) perms = 1 for count in counts: if count == 0: continue selected = min(count, remaining - count) combos = 1 for step in range(1, selected + 1): combos = combos * (remaining - step + 1) // step if combos >= limit: combos = limit break perms *= combos if perms >= limit: return limit remaining -= count return perms if k > count_permutations(half): return "" n = len(s) pal = [""] * n rank = k pos = 0 for _ in range(half_len): for i in range(26): if half[i] == 0: continue half[i] -= 1 suffix = count_permutations(half) if suffix >= rank: pal[pos] = chr(97 + i) pos += 1 break rank -= suffix half[i] += 1 if mid < 26: pal[half_len] = chr(97 + mid) for i in range(half_len): pal[n - 1 - i] = pal[i] return "".join(pal) -
func smallestPalindrome(s string, k int) string { const limit = 1_000_001 freq := [26]int{} for i := 0; i < len(s); i++ { freq[s[i]-'a']++ } odd, mid := 0, 26 for i, v := range freq { if v&1 == 1 { odd++ mid = i } } if odd > 1 { return "" } half := [26]int{} halfLen := 0 for i, v := range freq { half[i] = v / 2 halfLen += half[i] } countPermutations := func(counts [26]int) int { remaining := 0 for _, c := range counts { remaining += c } perms := 1 for _, count := range counts { if count == 0 { continue } selected := count if remaining-count < selected { selected = remaining - count } combos := 1 for step := 1; step <= selected; step++ { combos = combos * (remaining - step + 1) / step if combos >= limit { combos = limit break } } perms *= combos if perms >= limit { return limit } remaining -= count } return perms } if k > countPermutations(half) { return "" } n := len(s) pal := make([]byte, n) rank, pos := k, 0 for t := 0; t < halfLen; t++ { for i := 0; i < 26; i++ { if half[i] == 0 { continue } half[i]-- suffix := countPermutations(half) if suffix >= rank { pal[pos] = byte('a' + i) pos++ break } rank -= suffix half[i]++ } } if mid < 26 { pal[halfLen] = byte('a' + mid) } for i := 0; i < halfLen; i++ { pal[n-1-i] = pal[i] } return string(pal) }