From 283073b993f186327dab0a484b22322f102276b6 Mon Sep 17 00:00:00 2001 From: yanglbme Date: Tue, 4 Jun 2024 09:48:39 +0800 Subject: [PATCH] feat: add solutions to lc problem: No.409 No.0409.Longest Palindrome --- .../0409.Longest Palindrome/README.md | 105 ++++++----------- .../0409.Longest Palindrome/README_EN.md | 107 ++++++------------ .../0409.Longest Palindrome/Solution.cpp | 8 +- .../0409.Longest Palindrome/Solution.go | 8 +- .../0409.Longest Palindrome/Solution.java | 9 +- .../0409.Longest Palindrome/Solution.py | 6 +- .../0409.Longest Palindrome/Solution.rs | 25 ++-- .../0409.Longest Palindrome/Solution.ts | 16 +-- .../0409.Longest Palindrome/Solution2.ts | 16 --- 9 files changed, 99 insertions(+), 201 deletions(-) delete mode 100644 solution/0400-0499/0409.Longest Palindrome/Solution2.ts diff --git a/solution/0400-0499/0409.Longest Palindrome/README.md b/solution/0400-0499/0409.Longest Palindrome/README.md index 82be1184778cc..cb7100e471835 100644 --- a/solution/0400-0499/0409.Longest Palindrome/README.md +++ b/solution/0400-0499/0409.Longest Palindrome/README.md @@ -62,11 +62,11 @@ tags: 因此,我们可以先遍历字符串 $s$,统计每个字符出现的次数,记录在数组或哈希表 $cnt$ 中。 -然后,我们遍历 $cnt$,对于每个字符 $c$,如果 $cnt[c]$ 为偶数,则直接将 $cnt[c]$ 累加到答案 $ans$ 中;如果 $cnt[c]$ 为奇数,则将 $cnt[c] - 1$ 累加到 $ans$ 中,如果 $ans$ 为偶数,则将 $ans$ 增加 $1$。 +然后,我们遍历 $cnt$,对于每个次数 $v$,将 $v$ 除以 2 取整,再乘以 2,累加到答案 $ans$ 中。 -最后,我们返回 $ans$ 即可。 +最后,如果答案小于字符串 $s$ 的长度,则将答案加一,返回 $ans$。 -时间复杂度 $O(n)$,空间复杂度 $O(C)$。其中 $n$ 为字符串 $s$ 的长度;而 $C$ 为字符集的大小,本题中 $C = 128$。 +时间复杂度 $O(n + |\Sigma|)$,空间复杂度 $O(|\Sigma|)$。其中,$n$ 为字符串 $s$ 的长度,而 $|\Sigma|$ 为字符集大小,在本题中 $|\Sigma| = 128$。 @@ -76,10 +76,8 @@ tags: class Solution: def longestPalindrome(self, s: str) -> int: cnt = Counter(s) - ans = 0 - for v in cnt.values(): - ans += v - (v & 1) - ans += (ans & 1 ^ 1) and (v & 1) + ans = sum(v // 2 * 2 for v in cnt.values()) + ans += int(ans < len(s)) return ans ``` @@ -89,16 +87,15 @@ class Solution: class Solution { public int longestPalindrome(String s) { int[] cnt = new int[128]; - for (int i = 0; i < s.length(); ++i) { + int n = s.length(); + for (int i = 0; i < n; ++i) { ++cnt[s.charAt(i)]; } int ans = 0; for (int v : cnt) { - ans += v - (v & 1); - if (ans % 2 == 0 && v % 2 == 1) { - ++ans; - } + ans += v / 2 * 2; } + ans += ans < n ? 1 : 0; return ans; } } @@ -111,16 +108,14 @@ class Solution { public: int longestPalindrome(string s) { int cnt[128]{}; - for (char& c : s) { + for (char c : s) { ++cnt[c]; } int ans = 0; for (int v : cnt) { - ans += v - (v & 1); - if (ans % 2 == 0 && v % 2 == 1) { - ++ans; - } + ans += v / 2 * 2; } + ans += ans < s.size(); return ans; } }; @@ -135,10 +130,10 @@ func longestPalindrome(s string) (ans int) { cnt[c]++ } for _, v := range cnt { - ans += v - (v & 1) - if ans&1 == 0 && v&1 == 1 { - ans++ - } + ans += v / 2 * 2 + } + if ans < len(s) { + ans++ } return } @@ -148,17 +143,13 @@ func longestPalindrome(s string) (ans int) { ```ts function longestPalindrome(s: string): number { - let n = s.length; - let ans = 0; - let record = new Array(128).fill(0); - for (let i = 0; i < n; i++) { - record[s.charCodeAt(i)]++; - } - for (let i = 65; i < 128; i++) { - let count = record[i]; - ans += count % 2 == 0 ? count : count - 1; + const cnt: Record = {}; + for (const c of s) { + cnt[c] = (cnt[c] || 0) + 1; } - return ans < s.length ? ans + 1 : ans; + let ans = Object.values(cnt).reduce((acc, v) => acc + Math.floor(v / 2) * 2, 0); + ans += ans < s.length ? 1 : 0; + return ans; } ``` @@ -169,52 +160,22 @@ use std::collections::HashMap; impl Solution { pub fn longest_palindrome(s: String) -> i32 { - let mut map: HashMap = HashMap::new(); - for c in s.chars() { - map.insert(c, map.get(&c).unwrap_or(&0) + 1); + let mut cnt = HashMap::new(); + for ch in s.chars() { + *cnt.entry(ch).or_insert(0) += 1; } - let mut has_odd = false; - let mut res = 0; - for v in map.values() { - res += v; - if v % 2 == 1 { - has_odd = true; - res -= 1; - } - } - res + (if has_odd { 1 } else { 0 }) - } -} -``` - - - - - - -### 方法二 - - - -#### TypeScript + let mut ans = 0; + for &v in cnt.values() { + ans += (v / 2) * 2; + } -```ts -function longestPalindrome(s: string): number { - const map = new Map(); - for (const c of s) { - map.set(c, (map.get(c) ?? 0) + 1); - } - let hasOdd = false; - let res = 0; - for (const v of map.values()) { - res += v; - if (v & 1) { - hasOdd = true; - res--; + if ans < (s.len() as i32) { + ans += 1; } + + ans } - return res + (hasOdd ? 1 : 0); } ``` diff --git a/solution/0400-0499/0409.Longest Palindrome/README_EN.md b/solution/0400-0499/0409.Longest Palindrome/README_EN.md index e6c72da740477..e4a9170a87ff2 100644 --- a/solution/0400-0499/0409.Longest Palindrome/README_EN.md +++ b/solution/0400-0499/0409.Longest Palindrome/README_EN.md @@ -57,13 +57,13 @@ tags: A valid palindrome string can have at most one character that appears an odd number of times, and the rest of the characters appear an even number of times. -Therefore, we can first traverse the string $s$, count the number of times each character appears, and record it in an array or hash table $cnt$. +Therefore, we can first traverse the string $s$, count the number of occurrences of each character, and record it in an array or hash table $cnt$. -Then, we traverse $cnt$, for each character $c$, if $cnt[c]$ is even, then directly add $cnt[c]$ to the answer $ans$; if $cnt[c]$ is odd, then add $cnt[c] - 1$ to $ans$, if $ans$ is even, then increase $ans$ by $1$. +Then, we traverse $cnt$, for each count $v$, we divide $v$ by 2, take the integer part, multiply by 2, and add it to the answer $ans$. -Finally, we return $ans$. +Finally, if the answer is less than the length of the string $s$, we increment the answer by one and return $ans$. -The time complexity is $O(n)$, and the space complexity is $O(C)$. Here, $n$ is the length of the string $s$; and $C$ is the size of the character set, in this problem $C = 128$. +The time complexity is $O(n + |\Sigma|)$, and the space complexity is $O(|\Sigma|)$. Where $n$ is the length of the string $s$, and $|\Sigma|$ is the size of the character set. In this problem, $|\Sigma| = 128$. @@ -73,10 +73,8 @@ The time complexity is $O(n)$, and the space complexity is $O(C)$. Here, $n$ is class Solution: def longestPalindrome(self, s: str) -> int: cnt = Counter(s) - ans = 0 - for v in cnt.values(): - ans += v - (v & 1) - ans += (ans & 1 ^ 1) and (v & 1) + ans = sum(v // 2 * 2 for v in cnt.values()) + ans += int(ans < len(s)) return ans ``` @@ -86,16 +84,15 @@ class Solution: class Solution { public int longestPalindrome(String s) { int[] cnt = new int[128]; - for (int i = 0; i < s.length(); ++i) { + int n = s.length(); + for (int i = 0; i < n; ++i) { ++cnt[s.charAt(i)]; } int ans = 0; for (int v : cnt) { - ans += v - (v & 1); - if (ans % 2 == 0 && v % 2 == 1) { - ++ans; - } + ans += v / 2 * 2; } + ans += ans < n ? 1 : 0; return ans; } } @@ -108,16 +105,14 @@ class Solution { public: int longestPalindrome(string s) { int cnt[128]{}; - for (char& c : s) { + for (char c : s) { ++cnt[c]; } int ans = 0; for (int v : cnt) { - ans += v - (v & 1); - if (ans % 2 == 0 && v % 2 == 1) { - ++ans; - } + ans += v / 2 * 2; } + ans += ans < s.size(); return ans; } }; @@ -132,10 +127,10 @@ func longestPalindrome(s string) (ans int) { cnt[c]++ } for _, v := range cnt { - ans += v - (v & 1) - if ans&1 == 0 && v&1 == 1 { - ans++ - } + ans += v / 2 * 2 + } + if ans < len(s) { + ans++ } return } @@ -145,17 +140,13 @@ func longestPalindrome(s string) (ans int) { ```ts function longestPalindrome(s: string): number { - let n = s.length; - let ans = 0; - let record = new Array(128).fill(0); - for (let i = 0; i < n; i++) { - record[s.charCodeAt(i)]++; - } - for (let i = 65; i < 128; i++) { - let count = record[i]; - ans += count % 2 == 0 ? count : count - 1; + const cnt: Record = {}; + for (const c of s) { + cnt[c] = (cnt[c] || 0) + 1; } - return ans < s.length ? ans + 1 : ans; + let ans = Object.values(cnt).reduce((acc, v) => acc + Math.floor(v / 2) * 2, 0); + ans += ans < s.length ? 1 : 0; + return ans; } ``` @@ -166,52 +157,22 @@ use std::collections::HashMap; impl Solution { pub fn longest_palindrome(s: String) -> i32 { - let mut map: HashMap = HashMap::new(); - for c in s.chars() { - map.insert(c, map.get(&c).unwrap_or(&0) + 1); + let mut cnt = HashMap::new(); + for ch in s.chars() { + *cnt.entry(ch).or_insert(0) += 1; } - let mut has_odd = false; - let mut res = 0; - for v in map.values() { - res += v; - if v % 2 == 1 { - has_odd = true; - res -= 1; - } - } - res + (if has_odd { 1 } else { 0 }) - } -} -``` - - - - - - -### Solution 2 - - - -#### TypeScript + let mut ans = 0; + for &v in cnt.values() { + ans += (v / 2) * 2; + } -```ts -function longestPalindrome(s: string): number { - const map = new Map(); - for (const c of s) { - map.set(c, (map.get(c) ?? 0) + 1); - } - let hasOdd = false; - let res = 0; - for (const v of map.values()) { - res += v; - if (v & 1) { - hasOdd = true; - res--; + if ans < (s.len() as i32) { + ans += 1; } + + ans } - return res + (hasOdd ? 1 : 0); } ``` diff --git a/solution/0400-0499/0409.Longest Palindrome/Solution.cpp b/solution/0400-0499/0409.Longest Palindrome/Solution.cpp index 1f4d771ee84c3..8361d3becc147 100644 --- a/solution/0400-0499/0409.Longest Palindrome/Solution.cpp +++ b/solution/0400-0499/0409.Longest Palindrome/Solution.cpp @@ -2,16 +2,14 @@ class Solution { public: int longestPalindrome(string s) { int cnt[128]{}; - for (char& c : s) { + for (char c : s) { ++cnt[c]; } int ans = 0; for (int v : cnt) { - ans += v - (v & 1); - if (ans % 2 == 0 && v % 2 == 1) { - ++ans; - } + ans += v / 2 * 2; } + ans += ans < s.size(); return ans; } }; \ No newline at end of file diff --git a/solution/0400-0499/0409.Longest Palindrome/Solution.go b/solution/0400-0499/0409.Longest Palindrome/Solution.go index 703e13a564a9c..15ce46635927b 100644 --- a/solution/0400-0499/0409.Longest Palindrome/Solution.go +++ b/solution/0400-0499/0409.Longest Palindrome/Solution.go @@ -4,10 +4,10 @@ func longestPalindrome(s string) (ans int) { cnt[c]++ } for _, v := range cnt { - ans += v - (v & 1) - if ans&1 == 0 && v&1 == 1 { - ans++ - } + ans += v / 2 * 2 + } + if ans < len(s) { + ans++ } return } \ No newline at end of file diff --git a/solution/0400-0499/0409.Longest Palindrome/Solution.java b/solution/0400-0499/0409.Longest Palindrome/Solution.java index 63bf417364462..66aa76307d4e0 100644 --- a/solution/0400-0499/0409.Longest Palindrome/Solution.java +++ b/solution/0400-0499/0409.Longest Palindrome/Solution.java @@ -1,16 +1,15 @@ class Solution { public int longestPalindrome(String s) { int[] cnt = new int[128]; - for (int i = 0; i < s.length(); ++i) { + int n = s.length(); + for (int i = 0; i < n; ++i) { ++cnt[s.charAt(i)]; } int ans = 0; for (int v : cnt) { - ans += v - (v & 1); - if (ans % 2 == 0 && v % 2 == 1) { - ++ans; - } + ans += v / 2 * 2; } + ans += ans < n ? 1 : 0; return ans; } } \ No newline at end of file diff --git a/solution/0400-0499/0409.Longest Palindrome/Solution.py b/solution/0400-0499/0409.Longest Palindrome/Solution.py index 8a8773ddb16d4..f2332766eb907 100644 --- a/solution/0400-0499/0409.Longest Palindrome/Solution.py +++ b/solution/0400-0499/0409.Longest Palindrome/Solution.py @@ -1,8 +1,6 @@ class Solution: def longestPalindrome(self, s: str) -> int: cnt = Counter(s) - ans = 0 - for v in cnt.values(): - ans += v - (v & 1) - ans += (ans & 1 ^ 1) and (v & 1) + ans = sum(v // 2 * 2 for v in cnt.values()) + ans += int(ans < len(s)) return ans diff --git a/solution/0400-0499/0409.Longest Palindrome/Solution.rs b/solution/0400-0499/0409.Longest Palindrome/Solution.rs index 781576a7af8c0..488fdbaa28f47 100644 --- a/solution/0400-0499/0409.Longest Palindrome/Solution.rs +++ b/solution/0400-0499/0409.Longest Palindrome/Solution.rs @@ -2,19 +2,20 @@ use std::collections::HashMap; impl Solution { pub fn longest_palindrome(s: String) -> i32 { - let mut map: HashMap = HashMap::new(); - for c in s.chars() { - map.insert(c, map.get(&c).unwrap_or(&0) + 1); + let mut cnt = HashMap::new(); + for ch in s.chars() { + *cnt.entry(ch).or_insert(0) += 1; } - let mut has_odd = false; - let mut res = 0; - for v in map.values() { - res += v; - if v % 2 == 1 { - has_odd = true; - res -= 1; - } + + let mut ans = 0; + for &v in cnt.values() { + ans += (v / 2) * 2; + } + + if ans < (s.len() as i32) { + ans += 1; } - res + (if has_odd { 1 } else { 0 }) + + ans } } diff --git a/solution/0400-0499/0409.Longest Palindrome/Solution.ts b/solution/0400-0499/0409.Longest Palindrome/Solution.ts index 7d49f74198081..c0572d5112e1b 100644 --- a/solution/0400-0499/0409.Longest Palindrome/Solution.ts +++ b/solution/0400-0499/0409.Longest Palindrome/Solution.ts @@ -1,13 +1,9 @@ function longestPalindrome(s: string): number { - let n = s.length; - let ans = 0; - let record = new Array(128).fill(0); - for (let i = 0; i < n; i++) { - record[s.charCodeAt(i)]++; + const cnt: Record = {}; + for (const c of s) { + cnt[c] = (cnt[c] || 0) + 1; } - for (let i = 65; i < 128; i++) { - let count = record[i]; - ans += count % 2 == 0 ? count : count - 1; - } - return ans < s.length ? ans + 1 : ans; + let ans = Object.values(cnt).reduce((acc, v) => acc + Math.floor(v / 2) * 2, 0); + ans += ans < s.length ? 1 : 0; + return ans; } diff --git a/solution/0400-0499/0409.Longest Palindrome/Solution2.ts b/solution/0400-0499/0409.Longest Palindrome/Solution2.ts deleted file mode 100644 index 8f223668bcefa..0000000000000 --- a/solution/0400-0499/0409.Longest Palindrome/Solution2.ts +++ /dev/null @@ -1,16 +0,0 @@ -function longestPalindrome(s: string): number { - const map = new Map(); - for (const c of s) { - map.set(c, (map.get(c) ?? 0) + 1); - } - let hasOdd = false; - let res = 0; - for (const v of map.values()) { - res += v; - if (v & 1) { - hasOdd = true; - res--; - } - } - return res + (hasOdd ? 1 : 0); -}