Skip to content

Commit 8490191

Browse files
authored
feat: add solutions to lc problem: No.409 (doocs#3021)
No.0409.Longest Palindrome
1 parent d1eea19 commit 8490191

File tree

9 files changed

+99
-201
lines changed

9 files changed

+99
-201
lines changed

solution/0400-0499/0409.Longest Palindrome/README.md

+33-72
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,11 @@ tags:
6262

6363
因此,我们可以先遍历字符串 $s$,统计每个字符出现的次数,记录在数组或哈希表 $cnt$ 中。
6464

65-
然后,我们遍历 $cnt$,对于每个字符 $c$,如果 $cnt[c]$ 为偶数,则直接将 $cnt[c]$ 累加到答案 $ans$ 中;如果 $cnt[c]$ 为奇数,则将 $cnt[c] - 1$ 累加到 $ans$ 中,如果 $ans$ 为偶数,则将 $ans$ 增加 $1$
65+
然后,我们遍历 $cnt$,对于每个次数 $v$,将 $v$ 除以 2 取整,再乘以 2,累加到答案 $ans$
6666

67-
最后,我们返回 $ans$ 即可
67+
最后,如果答案小于字符串 $s$ 的长度,则将答案加一,返回 $ans$
6868

69-
时间复杂度 $O(n)$,空间复杂度 $O(C)$。其中 $n$ 为字符串 $s$ 的长度而 $C$ 为字符集的大小,本题中 $C = 128$。
69+
时间复杂度 $O(n + |\Sigma|)$,空间复杂度 $O(|\Sigma|)$。其中$n$ 为字符串 $s$ 的长度而 $|\Sigma|$ 为字符集大小,在本题中 $|\Sigma| = 128$。
7070

7171
<!-- tabs:start -->
7272

@@ -76,10 +76,8 @@ tags:
7676
class Solution:
7777
def longestPalindrome(self, s: str) -> int:
7878
cnt = Counter(s)
79-
ans = 0
80-
for v in cnt.values():
81-
ans += v - (v & 1)
82-
ans += (ans & 1 ^ 1) and (v & 1)
79+
ans = sum(v // 2 * 2 for v in cnt.values())
80+
ans += int(ans < len(s))
8381
return ans
8482
```
8583

@@ -89,16 +87,15 @@ class Solution:
8987
class Solution {
9088
public int longestPalindrome(String s) {
9189
int[] cnt = new int[128];
92-
for (int i = 0; i < s.length(); ++i) {
90+
int n = s.length();
91+
for (int i = 0; i < n; ++i) {
9392
++cnt[s.charAt(i)];
9493
}
9594
int ans = 0;
9695
for (int v : cnt) {
97-
ans += v - (v & 1);
98-
if (ans % 2 == 0 && v % 2 == 1) {
99-
++ans;
100-
}
96+
ans += v / 2 * 2;
10197
}
98+
ans += ans < n ? 1 : 0;
10299
return ans;
103100
}
104101
}
@@ -111,16 +108,14 @@ class Solution {
111108
public:
112109
int longestPalindrome(string s) {
113110
int cnt[128]{};
114-
for (char& c : s) {
111+
for (char c : s) {
115112
++cnt[c];
116113
}
117114
int ans = 0;
118115
for (int v : cnt) {
119-
ans += v - (v & 1);
120-
if (ans % 2 == 0 && v % 2 == 1) {
121-
++ans;
122-
}
116+
ans += v / 2 * 2;
123117
}
118+
ans += ans < s.size();
124119
return ans;
125120
}
126121
};
@@ -135,10 +130,10 @@ func longestPalindrome(s string) (ans int) {
135130
cnt[c]++
136131
}
137132
for _, v := range cnt {
138-
ans += v - (v & 1)
139-
if ans&1 == 0 && v&1 == 1 {
140-
ans++
141-
}
133+
ans += v / 2 * 2
134+
}
135+
if ans < len(s) {
136+
ans++
142137
}
143138
return
144139
}
@@ -148,17 +143,13 @@ func longestPalindrome(s string) (ans int) {
148143

149144
```ts
150145
function longestPalindrome(s: string): number {
151-
let n = s.length;
152-
let ans = 0;
153-
let record = new Array(128).fill(0);
154-
for (let i = 0; i < n; i++) {
155-
record[s.charCodeAt(i)]++;
156-
}
157-
for (let i = 65; i < 128; i++) {
158-
let count = record[i];
159-
ans += count % 2 == 0 ? count : count - 1;
146+
const cnt: Record<string, number> = {};
147+
for (const c of s) {
148+
cnt[c] = (cnt[c] || 0) + 1;
160149
}
161-
return ans < s.length ? ans + 1 : ans;
150+
let ans = Object.values(cnt).reduce((acc, v) => acc + Math.floor(v / 2) * 2, 0);
151+
ans += ans < s.length ? 1 : 0;
152+
return ans;
162153
}
163154
```
164155

@@ -169,52 +160,22 @@ use std::collections::HashMap;
169160

170161
impl Solution {
171162
pub fn longest_palindrome(s: String) -> i32 {
172-
let mut map: HashMap<char, i32> = HashMap::new();
173-
for c in s.chars() {
174-
map.insert(c, map.get(&c).unwrap_or(&0) + 1);
163+
let mut cnt = HashMap::new();
164+
for ch in s.chars() {
165+
*cnt.entry(ch).or_insert(0) += 1;
175166
}
176-
let mut has_odd = false;
177-
let mut res = 0;
178-
for v in map.values() {
179-
res += v;
180-
if v % 2 == 1 {
181-
has_odd = true;
182-
res -= 1;
183-
}
184-
}
185-
res + (if has_odd { 1 } else { 0 })
186-
}
187-
}
188-
```
189-
190-
<!-- tabs:end -->
191167

192-
<!-- solution:end -->
193-
194-
<!-- solution:start -->
195-
196-
### 方法二
197-
198-
<!-- tabs:start -->
199-
200-
#### TypeScript
168+
let mut ans = 0;
169+
for &v in cnt.values() {
170+
ans += (v / 2) * 2;
171+
}
201172

202-
```ts
203-
function longestPalindrome(s: string): number {
204-
const map = new Map();
205-
for (const c of s) {
206-
map.set(c, (map.get(c) ?? 0) + 1);
207-
}
208-
let hasOdd = false;
209-
let res = 0;
210-
for (const v of map.values()) {
211-
res += v;
212-
if (v & 1) {
213-
hasOdd = true;
214-
res--;
173+
if ans < (s.len() as i32) {
174+
ans += 1;
215175
}
176+
177+
ans
216178
}
217-
return res + (hasOdd ? 1 : 0);
218179
}
219180
```
220181

solution/0400-0499/0409.Longest Palindrome/README_EN.md

+34-73
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,13 @@ tags:
5757

5858
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.
5959

60-
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$.
60+
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$.
6161

62-
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$.
62+
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$.
6363

64-
Finally, we return $ans$.
64+
Finally, if the answer is less than the length of the string $s$, we increment the answer by one and return $ans$.
6565

66-
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$.
66+
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$.
6767

6868
<!-- tabs:start -->
6969

@@ -73,10 +73,8 @@ The time complexity is $O(n)$, and the space complexity is $O(C)$. Here, $n$ is
7373
class Solution:
7474
def longestPalindrome(self, s: str) -> int:
7575
cnt = Counter(s)
76-
ans = 0
77-
for v in cnt.values():
78-
ans += v - (v & 1)
79-
ans += (ans & 1 ^ 1) and (v & 1)
76+
ans = sum(v // 2 * 2 for v in cnt.values())
77+
ans += int(ans < len(s))
8078
return ans
8179
```
8280

@@ -86,16 +84,15 @@ class Solution:
8684
class Solution {
8785
public int longestPalindrome(String s) {
8886
int[] cnt = new int[128];
89-
for (int i = 0; i < s.length(); ++i) {
87+
int n = s.length();
88+
for (int i = 0; i < n; ++i) {
9089
++cnt[s.charAt(i)];
9190
}
9291
int ans = 0;
9392
for (int v : cnt) {
94-
ans += v - (v & 1);
95-
if (ans % 2 == 0 && v % 2 == 1) {
96-
++ans;
97-
}
93+
ans += v / 2 * 2;
9894
}
95+
ans += ans < n ? 1 : 0;
9996
return ans;
10097
}
10198
}
@@ -108,16 +105,14 @@ class Solution {
108105
public:
109106
int longestPalindrome(string s) {
110107
int cnt[128]{};
111-
for (char& c : s) {
108+
for (char c : s) {
112109
++cnt[c];
113110
}
114111
int ans = 0;
115112
for (int v : cnt) {
116-
ans += v - (v & 1);
117-
if (ans % 2 == 0 && v % 2 == 1) {
118-
++ans;
119-
}
113+
ans += v / 2 * 2;
120114
}
115+
ans += ans < s.size();
121116
return ans;
122117
}
123118
};
@@ -132,10 +127,10 @@ func longestPalindrome(s string) (ans int) {
132127
cnt[c]++
133128
}
134129
for _, v := range cnt {
135-
ans += v - (v & 1)
136-
if ans&1 == 0 && v&1 == 1 {
137-
ans++
138-
}
130+
ans += v / 2 * 2
131+
}
132+
if ans < len(s) {
133+
ans++
139134
}
140135
return
141136
}
@@ -145,17 +140,13 @@ func longestPalindrome(s string) (ans int) {
145140

146141
```ts
147142
function longestPalindrome(s: string): number {
148-
let n = s.length;
149-
let ans = 0;
150-
let record = new Array(128).fill(0);
151-
for (let i = 0; i < n; i++) {
152-
record[s.charCodeAt(i)]++;
153-
}
154-
for (let i = 65; i < 128; i++) {
155-
let count = record[i];
156-
ans += count % 2 == 0 ? count : count - 1;
143+
const cnt: Record<string, number> = {};
144+
for (const c of s) {
145+
cnt[c] = (cnt[c] || 0) + 1;
157146
}
158-
return ans < s.length ? ans + 1 : ans;
147+
let ans = Object.values(cnt).reduce((acc, v) => acc + Math.floor(v / 2) * 2, 0);
148+
ans += ans < s.length ? 1 : 0;
149+
return ans;
159150
}
160151
```
161152

@@ -166,52 +157,22 @@ use std::collections::HashMap;
166157

167158
impl Solution {
168159
pub fn longest_palindrome(s: String) -> i32 {
169-
let mut map: HashMap<char, i32> = HashMap::new();
170-
for c in s.chars() {
171-
map.insert(c, map.get(&c).unwrap_or(&0) + 1);
160+
let mut cnt = HashMap::new();
161+
for ch in s.chars() {
162+
*cnt.entry(ch).or_insert(0) += 1;
172163
}
173-
let mut has_odd = false;
174-
let mut res = 0;
175-
for v in map.values() {
176-
res += v;
177-
if v % 2 == 1 {
178-
has_odd = true;
179-
res -= 1;
180-
}
181-
}
182-
res + (if has_odd { 1 } else { 0 })
183-
}
184-
}
185-
```
186-
187-
<!-- tabs:end -->
188164

189-
<!-- solution:end -->
190-
191-
<!-- solution:start -->
192-
193-
### Solution 2
194-
195-
<!-- tabs:start -->
196-
197-
#### TypeScript
165+
let mut ans = 0;
166+
for &v in cnt.values() {
167+
ans += (v / 2) * 2;
168+
}
198169

199-
```ts
200-
function longestPalindrome(s: string): number {
201-
const map = new Map();
202-
for (const c of s) {
203-
map.set(c, (map.get(c) ?? 0) + 1);
204-
}
205-
let hasOdd = false;
206-
let res = 0;
207-
for (const v of map.values()) {
208-
res += v;
209-
if (v & 1) {
210-
hasOdd = true;
211-
res--;
170+
if ans < (s.len() as i32) {
171+
ans += 1;
212172
}
173+
174+
ans
213175
}
214-
return res + (hasOdd ? 1 : 0);
215176
}
216177
```
217178

solution/0400-0499/0409.Longest Palindrome/Solution.cpp

+3-5
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,14 @@ class Solution {
22
public:
33
int longestPalindrome(string s) {
44
int cnt[128]{};
5-
for (char& c : s) {
5+
for (char c : s) {
66
++cnt[c];
77
}
88
int ans = 0;
99
for (int v : cnt) {
10-
ans += v - (v & 1);
11-
if (ans % 2 == 0 && v % 2 == 1) {
12-
++ans;
13-
}
10+
ans += v / 2 * 2;
1411
}
12+
ans += ans < s.size();
1513
return ans;
1614
}
1715
};

solution/0400-0499/0409.Longest Palindrome/Solution.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ func longestPalindrome(s string) (ans int) {
44
cnt[c]++
55
}
66
for _, v := range cnt {
7-
ans += v - (v & 1)
8-
if ans&1 == 0 && v&1 == 1 {
9-
ans++
10-
}
7+
ans += v / 2 * 2
8+
}
9+
if ans < len(s) {
10+
ans++
1111
}
1212
return
1313
}

0 commit comments

Comments
 (0)