diff --git a/solution/3500-3599/3517.Smallest Palindromic Rearrangement I/README.md b/solution/3500-3599/3517.Smallest Palindromic Rearrangement I/README.md index dc507ba21649e..4d72567c3fbe4 100644 --- a/solution/3500-3599/3517.Smallest Palindromic Rearrangement I/README.md +++ b/solution/3500-3599/3517.Smallest Palindromic Rearrangement I/README.md @@ -86,32 +86,165 @@ tags: -### 方法一 +### 方法一:计数 + +我们首先统计字符串中每个字符的出现次数,记录在哈希表或数组 $\textit{cnt}$ 中。由于字符串是回文字符串,因此每个字符的出现次数要么是偶数次,要么有且仅有一个字符出现奇数次。 + +接下来,我们从字典序最小的字符开始,依次将每个字符的一半次数添加到结果字符串的前半部分 $\textit{t}$ 中。如果某个字符出现了奇数次,我们将该字符记录为中间字符 $\textit{ch}$。最后,我们将 $\textit{t}$、$\textit{ch}$ 和 $\textit{t}$ 的反转拼接起来,得到最终的按字典序排列的最小回文排列。 + +时间复杂度 $O(n)$,其中 $n$ 是字符串的长度。空间复杂度 $O(|\Sigma|)$,其中 $|\Sigma|$ 是字符集的大小,本题中 $|\Sigma|=26$。 #### Python3 ```python - +class Solution: + def smallestPalindrome(self, s: str) -> str: + cnt = Counter(s) + t = [] + ch = "" + for c in ascii_lowercase: + v = cnt[c] // 2 + t.append(c * v) + cnt[c] -= v * 2 + if cnt[c] == 1: + ch = c + ans = "".join(t) + ans = ans + ch + ans[::-1] + return ans ``` #### Java ```java - +class Solution { + public String smallestPalindrome(String s) { + int[] cnt = new int[26]; + for (char c : s.toCharArray()) { + cnt[c - 'a']++; + } + + StringBuilder t = new StringBuilder(); + String ch = ""; + + for (char c = 'a'; c <= 'z'; c++) { + int idx = c - 'a'; + int v = cnt[idx] / 2; + if (v > 0) { + t.append(String.valueOf(c).repeat(v)); + } + cnt[idx] -= v * 2; + if (cnt[idx] == 1) { + ch = String.valueOf(c); + } + } + + String ans = t.toString(); + ans = ans + ch + new StringBuilder(ans).reverse(); + return ans; + } +} ``` #### C++ ```cpp - +class Solution { +public: + string smallestPalindrome(string s) { + vector cnt(26); + for (char c : s) { + cnt[c - 'a']++; + } + string t = ""; + string ch = ""; + for (char c = 'a'; c <= 'z'; ++c) { + int v = cnt[c - 'a'] / 2; + if (v > 0) { + t.append(v, c); + } + cnt[c - 'a'] -= v * 2; + if (cnt[c - 'a'] == 1) { + ch = string(1, c); + } + } + string ans = t; + ans += ch; + string rev = t; + reverse(rev.begin(), rev.end()); + ans += rev; + return ans; + } +}; ``` #### Go ```go +func smallestPalindrome(s string) string { + cnt := make([]int, 26) + for i := 0; i < len(s); i++ { + cnt[s[i]-'a']++ + } + + t := make([]byte, 0, len(s)/2) + var ch byte + for c := byte('a'); c <= 'z'; c++ { + v := cnt[c-'a'] / 2 + for i := 0; i < v; i++ { + t = append(t, c) + } + cnt[c-'a'] -= v * 2 + if cnt[c-'a'] == 1 { + ch = c + } + } + + totalLen := len(t) * 2 + if ch != 0 { + totalLen++ + } + var sb strings.Builder + sb.Grow(totalLen) + + sb.Write(t) + if ch != 0 { + sb.WriteByte(ch) + } + for i := len(t) - 1; i >= 0; i-- { + sb.WriteByte(t[i]) + } + return sb.String() +} +``` +#### TypeScript + +```ts +function smallestPalindrome(s: string): string { + const ascii_lowercase = 'abcdefghijklmnopqrstuvwxyz'; + const cnt = new Array(26).fill(0); + for (const chKey of s) { + cnt[chKey.charCodeAt(0) - 97]++; + } + + const t: string[] = []; + let ch = ''; + for (let i = 0; i < 26; i++) { + const c = ascii_lowercase[i]; + const v = Math.floor(cnt[i] / 2); + t.push(c.repeat(v)); + cnt[i] -= v * 2; + if (cnt[i] === 1) { + ch = c; + } + } + + let ans = t.join(''); + ans = ans + ch + ans.split('').reverse().join(''); + return ans; +} ``` diff --git a/solution/3500-3599/3517.Smallest Palindromic Rearrangement I/README_EN.md b/solution/3500-3599/3517.Smallest Palindromic Rearrangement I/README_EN.md index fa24d44af8d82..0d687033a4258 100644 --- a/solution/3500-3599/3517.Smallest Palindromic Rearrangement I/README_EN.md +++ b/solution/3500-3599/3517.Smallest Palindromic Rearrangement I/README_EN.md @@ -76,32 +76,165 @@ tags: -### Solution 1 +### Solution 1: Counting + +We first count the occurrence of each character in the string and record it in a hash table or array $\textit{cnt}$. Since the string is a palindrome, the count of each character is either even, or there is exactly one character with an odd count. + +Next, starting from the lexicographically smallest character, we sequentially add half of each character's count to the first half of the result string $\textit{t}$. If a character appears an odd number of times, we record it as the middle character $\textit{ch}$. Finally, we concatenate $\textit{t}$, $\textit{ch}$, and the reverse of $\textit{t}$ to obtain the final lexicographically smallest palindromic rearrangement. + +The time complexity is $O(n)$, where $n$ is the length of the string. The space complexity is $O(|\Sigma|)$, where $|\Sigma|$ is the size of the character set, which is $26$ in this problem. #### Python3 ```python - +class Solution: + def smallestPalindrome(self, s: str) -> str: + cnt = Counter(s) + t = [] + ch = "" + for c in ascii_lowercase: + v = cnt[c] // 2 + t.append(c * v) + cnt[c] -= v * 2 + if cnt[c] == 1: + ch = c + ans = "".join(t) + ans = ans + ch + ans[::-1] + return ans ``` #### Java ```java - +class Solution { + public String smallestPalindrome(String s) { + int[] cnt = new int[26]; + for (char c : s.toCharArray()) { + cnt[c - 'a']++; + } + + StringBuilder t = new StringBuilder(); + String ch = ""; + + for (char c = 'a'; c <= 'z'; c++) { + int idx = c - 'a'; + int v = cnt[idx] / 2; + if (v > 0) { + t.append(String.valueOf(c).repeat(v)); + } + cnt[idx] -= v * 2; + if (cnt[idx] == 1) { + ch = String.valueOf(c); + } + } + + String ans = t.toString(); + ans = ans + ch + new StringBuilder(ans).reverse(); + return ans; + } +} ``` #### C++ ```cpp - +class Solution { +public: + string smallestPalindrome(string s) { + vector cnt(26); + for (char c : s) { + cnt[c - 'a']++; + } + string t = ""; + string ch = ""; + for (char c = 'a'; c <= 'z'; ++c) { + int v = cnt[c - 'a'] / 2; + if (v > 0) { + t.append(v, c); + } + cnt[c - 'a'] -= v * 2; + if (cnt[c - 'a'] == 1) { + ch = string(1, c); + } + } + string ans = t; + ans += ch; + string rev = t; + reverse(rev.begin(), rev.end()); + ans += rev; + return ans; + } +}; ``` #### Go ```go +func smallestPalindrome(s string) string { + cnt := make([]int, 26) + for i := 0; i < len(s); i++ { + cnt[s[i]-'a']++ + } + + t := make([]byte, 0, len(s)/2) + var ch byte + for c := byte('a'); c <= 'z'; c++ { + v := cnt[c-'a'] / 2 + for i := 0; i < v; i++ { + t = append(t, c) + } + cnt[c-'a'] -= v * 2 + if cnt[c-'a'] == 1 { + ch = c + } + } + + totalLen := len(t) * 2 + if ch != 0 { + totalLen++ + } + var sb strings.Builder + sb.Grow(totalLen) + + sb.Write(t) + if ch != 0 { + sb.WriteByte(ch) + } + for i := len(t) - 1; i >= 0; i-- { + sb.WriteByte(t[i]) + } + return sb.String() +} +``` +#### TypeScript + +```ts +function smallestPalindrome(s: string): string { + const ascii_lowercase = 'abcdefghijklmnopqrstuvwxyz'; + const cnt = new Array(26).fill(0); + for (const chKey of s) { + cnt[chKey.charCodeAt(0) - 97]++; + } + + const t: string[] = []; + let ch = ''; + for (let i = 0; i < 26; i++) { + const c = ascii_lowercase[i]; + const v = Math.floor(cnt[i] / 2); + t.push(c.repeat(v)); + cnt[i] -= v * 2; + if (cnt[i] === 1) { + ch = c; + } + } + + let ans = t.join(''); + ans = ans + ch + ans.split('').reverse().join(''); + return ans; +} ``` diff --git a/solution/3500-3599/3517.Smallest Palindromic Rearrangement I/Solution.cpp b/solution/3500-3599/3517.Smallest Palindromic Rearrangement I/Solution.cpp new file mode 100644 index 0000000000000..ece8560d454db --- /dev/null +++ b/solution/3500-3599/3517.Smallest Palindromic Rearrangement I/Solution.cpp @@ -0,0 +1,27 @@ +class Solution { +public: + string smallestPalindrome(string s) { + vector cnt(26); + for (char c : s) { + cnt[c - 'a']++; + } + string t = ""; + string ch = ""; + for (char c = 'a'; c <= 'z'; ++c) { + int v = cnt[c - 'a'] / 2; + if (v > 0) { + t.append(v, c); + } + cnt[c - 'a'] -= v * 2; + if (cnt[c - 'a'] == 1) { + ch = string(1, c); + } + } + string ans = t; + ans += ch; + string rev = t; + reverse(rev.begin(), rev.end()); + ans += rev; + return ans; + } +}; diff --git a/solution/3500-3599/3517.Smallest Palindromic Rearrangement I/Solution.go b/solution/3500-3599/3517.Smallest Palindromic Rearrangement I/Solution.go new file mode 100644 index 0000000000000..cab2f7e6a4f9f --- /dev/null +++ b/solution/3500-3599/3517.Smallest Palindromic Rearrangement I/Solution.go @@ -0,0 +1,35 @@ +func smallestPalindrome(s string) string { + cnt := make([]int, 26) + for i := 0; i < len(s); i++ { + cnt[s[i]-'a']++ + } + + t := make([]byte, 0, len(s)/2) + var ch byte + for c := byte('a'); c <= 'z'; c++ { + v := cnt[c-'a'] / 2 + for i := 0; i < v; i++ { + t = append(t, c) + } + cnt[c-'a'] -= v * 2 + if cnt[c-'a'] == 1 { + ch = c + } + } + + totalLen := len(t) * 2 + if ch != 0 { + totalLen++ + } + var sb strings.Builder + sb.Grow(totalLen) + + sb.Write(t) + if ch != 0 { + sb.WriteByte(ch) + } + for i := len(t) - 1; i >= 0; i-- { + sb.WriteByte(t[i]) + } + return sb.String() +} diff --git a/solution/3500-3599/3517.Smallest Palindromic Rearrangement I/Solution.java b/solution/3500-3599/3517.Smallest Palindromic Rearrangement I/Solution.java new file mode 100644 index 0000000000000..e0e7eb9f43201 --- /dev/null +++ b/solution/3500-3599/3517.Smallest Palindromic Rearrangement I/Solution.java @@ -0,0 +1,27 @@ +class Solution { + public String smallestPalindrome(String s) { + int[] cnt = new int[26]; + for (char c : s.toCharArray()) { + cnt[c - 'a']++; + } + + StringBuilder t = new StringBuilder(); + String ch = ""; + + for (char c = 'a'; c <= 'z'; c++) { + int idx = c - 'a'; + int v = cnt[idx] / 2; + if (v > 0) { + t.append(String.valueOf(c).repeat(v)); + } + cnt[idx] -= v * 2; + if (cnt[idx] == 1) { + ch = String.valueOf(c); + } + } + + String ans = t.toString(); + ans = ans + ch + new StringBuilder(ans).reverse(); + return ans; + } +} diff --git a/solution/3500-3599/3517.Smallest Palindromic Rearrangement I/Solution.py b/solution/3500-3599/3517.Smallest Palindromic Rearrangement I/Solution.py new file mode 100644 index 0000000000000..522995ed12f77 --- /dev/null +++ b/solution/3500-3599/3517.Smallest Palindromic Rearrangement I/Solution.py @@ -0,0 +1,14 @@ +class Solution: + def smallestPalindrome(self, s: str) -> str: + cnt = Counter(s) + t = [] + ch = "" + for c in ascii_lowercase: + v = cnt[c] // 2 + t.append(c * v) + cnt[c] -= v * 2 + if cnt[c] == 1: + ch = c + ans = "".join(t) + ans = ans + ch + ans[::-1] + return ans diff --git a/solution/3500-3599/3517.Smallest Palindromic Rearrangement I/Solution.ts b/solution/3500-3599/3517.Smallest Palindromic Rearrangement I/Solution.ts new file mode 100644 index 0000000000000..64393f2417769 --- /dev/null +++ b/solution/3500-3599/3517.Smallest Palindromic Rearrangement I/Solution.ts @@ -0,0 +1,23 @@ +function smallestPalindrome(s: string): string { + const ascii_lowercase = 'abcdefghijklmnopqrstuvwxyz'; + const cnt = new Array(26).fill(0); + for (const chKey of s) { + cnt[chKey.charCodeAt(0) - 97]++; + } + + const t: string[] = []; + let ch = ''; + for (let i = 0; i < 26; i++) { + const c = ascii_lowercase[i]; + const v = Math.floor(cnt[i] / 2); + t.push(c.repeat(v)); + cnt[i] -= v * 2; + if (cnt[i] === 1) { + ch = c; + } + } + + let ans = t.join(''); + ans = ans + ch + ans.split('').reverse().join(''); + return ans; +}