Skip to content

Commit 2659300

Browse files
authored
feat: add solutions to lc problem: No.2516 (#2581)
No.2516.Take K of Each Character From Left and Right
1 parent 69c6efc commit 2659300

File tree

8 files changed

+199
-153
lines changed

8 files changed

+199
-153
lines changed

solution/2500-2599/2516.Take K of Each Character From Left and Right/README.md

+64-52
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,15 @@
4848

4949
### 方法一:滑动窗口
5050

51-
我们先用哈希表或者一个长度为 $3$ 的数组 `cnt` 统计字符串 $s$ 中每个字符的个数,如果有字符的个数小于 $k$ 个,则无法取到,提前返回 $-1$。
51+
我们先用哈希表或者一个长度为 $3$ 的数组 $cnt$ 统计字符串 $s$ 中每个字符的个数,如果有字符的个数小于 $k$ 个,则无法取到,提前返回 $-1$。
5252

5353
题目要我们在字符串左侧以及右侧取走字符,最终取到的每种字符的个数都不少于 $k$ 个。我们不妨反着考虑问题,取走中间某个窗口大小的字符串,使得剩下的两侧字符串中,每种字符的个数都不少于 $k$ 个。
5454

5555
因此,我们维护一个滑动窗口,用指针 $j$ 和 $i$ 分别表示窗口的左右边界,窗口内的字符串是我们要取走的。我们每一次移动右边界 $i$,将对应的字符 $s[i]$ 加入到窗口中(也即取走一个字符 $s[i]$),此时如果 $cnt[s[i]]$ 个数小于 $k$,那么我们循环移动左边界 $j$,直到 $cnt[s[i]]$ 个数不小于 $k$ 为止。此时的窗口大小为 $i - j + 1$,更新最大窗口。
5656

5757
最终的答案就是字符串 $s$ 的长度减去最大窗口的大小。
5858

59-
时间复杂度 $O(n)$,空间复杂度 $O(1)$。其中 $n$ 为字符串 $s$ 的长度。
59+
时间复杂度 $O(n)$,其中 $n$ 为字符串 $s$ 的长度。空间复杂度 $O(1)$
6060

6161
<!-- tabs:start -->
6262

@@ -66,14 +66,14 @@ class Solution:
6666
cnt = Counter(s)
6767
if any(cnt[c] < k for c in "abc"):
6868
return -1
69-
ans = j = 0
69+
mx = j = 0
7070
for i, c in enumerate(s):
7171
cnt[c] -= 1
7272
while cnt[c] < k:
7373
cnt[s[j]] += 1
7474
j += 1
75-
ans = max(ans, i - j + 1)
76-
return len(s) - ans
75+
mx = max(mx, i - j + 1)
76+
return len(s) - mx
7777
```
7878

7979
```java
@@ -84,19 +84,21 @@ class Solution {
8484
for (int i = 0; i < n; ++i) {
8585
++cnt[s.charAt(i) - 'a'];
8686
}
87-
if (cnt[0] < k || cnt[1] < k || cnt[2] < k) {
88-
return -1;
87+
for (int x : cnt) {
88+
if (x < k) {
89+
return -1;
90+
}
8991
}
90-
int ans = 0, j = 0;
92+
int mx = 0, j = 0;
9193
for (int i = 0; i < n; ++i) {
9294
int c = s.charAt(i) - 'a';
9395
--cnt[c];
9496
while (cnt[c] < k) {
9597
++cnt[s.charAt(j++) - 'a'];
9698
}
97-
ans = Math.max(ans, i - j + 1);
99+
mx = Math.max(mx, i - j + 1);
98100
}
99-
return n - ans;
101+
return n - mx;
100102
}
101103
}
102104
```
@@ -105,20 +107,26 @@ class Solution {
105107
class Solution {
106108
public:
107109
int takeCharacters(string s, int k) {
108-
int cnt[3] = {0};
109-
for (char& c : s) ++cnt[c - 'a'];
110-
if (cnt[0] < k || cnt[1] < k || cnt[2] < k) return -1;
111-
int ans = 0, j = 0;
112-
int n = s.size();
110+
int cnt[3]{};
111+
int n = s.length();
112+
for (int i = 0; i < n; ++i) {
113+
++cnt[s[i] - 'a'];
114+
}
115+
for (int x : cnt) {
116+
if (x < k) {
117+
return -1;
118+
}
119+
}
120+
int mx = 0, j = 0;
113121
for (int i = 0; i < n; ++i) {
114122
int c = s[i] - 'a';
115123
--cnt[c];
116124
while (cnt[c] < k) {
117125
++cnt[s[j++] - 'a'];
118126
}
119-
ans = max(ans, i - j + 1);
127+
mx = max(mx, i - j + 1);
120128
}
121-
return n - ans;
129+
return n - mx;
122130
}
123131
};
124132
```
@@ -129,70 +137,74 @@ func takeCharacters(s string, k int) int {
129137
for _, c := range s {
130138
cnt[c-'a']++
131139
}
132-
if cnt[0] < k || cnt[1] < k || cnt[2] < k {
133-
return -1
140+
for _, x := range cnt {
141+
if x < k {
142+
return -1
143+
}
134144
}
135-
ans, j := 0, 0
145+
mx, j := 0, 0
136146
for i, c := range s {
137147
c -= 'a'
138-
cnt[c]--
139-
for cnt[c] < k {
148+
for cnt[c]--; cnt[c] < k; j++ {
140149
cnt[s[j]-'a']++
141-
j++
142150
}
143-
ans = max(ans, i-j+1)
151+
mx = max(mx, i-j+1)
144152
}
145-
return len(s) - ans
153+
return len(s) - mx
146154
}
147155
```
148156

149157
```ts
150158
function takeCharacters(s: string, k: number): number {
151-
const getIndex = (c: string) => c.charCodeAt(0) - 'a'.charCodeAt(0);
152-
const count = [0, 0, 0];
159+
const idx = (c: string) => c.charCodeAt(0) - 97;
160+
const cnt: number[] = Array(3).fill(0);
153161
for (const c of s) {
154-
count[getIndex(c)]++;
162+
++cnt[idx(c)];
155163
}
156-
if (count.some(v => v < k)) {
164+
if (cnt.some(v => v < k)) {
157165
return -1;
158166
}
159167
const n = s.length;
160-
let ans = 0;
161-
for (let i = 0, j = 0; j < n; j++) {
162-
count[getIndex(s[j])]--;
163-
while (count[getIndex(s[j])] < k) {
164-
count[getIndex(s[i])]++;
165-
i++;
168+
let [mx, j] = [0, 0];
169+
for (let i = 0; i < n; ++i) {
170+
const c = idx(s[i]);
171+
--cnt[c];
172+
while (cnt[c] < k) {
173+
++cnt[idx(s[j++])];
166174
}
167-
ans = Math.max(ans, j - i + 1);
175+
mx = Math.max(mx, i - j + 1);
168176
}
169-
return n - ans;
177+
return n - mx;
170178
}
171179
```
172180

173181
```rust
182+
use std::collections::HashMap;
183+
174184
impl Solution {
175185
pub fn take_characters(s: String, k: i32) -> i32 {
176-
let s = s.as_bytes();
177-
let mut count = vec![0; 3];
178-
for c in s.iter() {
179-
count[(c - b'a') as usize] += 1;
186+
let mut cnt: HashMap<char, i32> = HashMap::new();
187+
for c in s.chars() {
188+
*cnt.entry(c).or_insert(0) += 1;
180189
}
181-
if count.iter().any(|v| *v < k) {
190+
191+
if "abc".chars().any(|c| cnt.get(&c).unwrap_or(&0) < &k) {
182192
return -1;
183193
}
184-
let n = s.len();
185-
let mut ans = 0;
186-
let mut i = 0;
187-
for j in 0..n {
188-
count[(s[j] - b'a') as usize] -= 1;
189-
while count[(s[j] - b'a') as usize] < k {
190-
count[(s[i] - b'a') as usize] += 1;
191-
i += 1;
194+
195+
let mut mx = 0;
196+
let mut j = 0;
197+
let mut cs = s.chars().collect::<Vec<char>>();
198+
for i in 0..cs.len() {
199+
let c = cs[i];
200+
*cnt.get_mut(&c).unwrap() -= 1;
201+
while cnt.get(&c).unwrap() < &k {
202+
*cnt.get_mut(&cs[j]).unwrap() += 1;
203+
j += 1;
192204
}
193-
ans = ans.max(j - i + 1);
205+
mx = mx.max(i - j + 1);
194206
}
195-
(n - ans) as i32
207+
(cs.len() as i32) - (mx as i32)
196208
}
197209
}
198210
```

0 commit comments

Comments
 (0)