48
48
49
49
### 方法一:滑动窗口
50
50
51
- 我们先用哈希表或者一个长度为 $3$ 的数组 ` cnt ` 统计字符串 $s$ 中每个字符的个数,如果有字符的个数小于 $k$ 个,则无法取到,提前返回 $-1$。
51
+ 我们先用哈希表或者一个长度为 $3$ 的数组 $ cnt$ 统计字符串 $s$ 中每个字符的个数,如果有字符的个数小于 $k$ 个,则无法取到,提前返回 $-1$。
52
52
53
53
题目要我们在字符串左侧以及右侧取走字符,最终取到的每种字符的个数都不少于 $k$ 个。我们不妨反着考虑问题,取走中间某个窗口大小的字符串,使得剩下的两侧字符串中,每种字符的个数都不少于 $k$ 个。
54
54
55
55
因此,我们维护一个滑动窗口,用指针 $j$ 和 $i$ 分别表示窗口的左右边界,窗口内的字符串是我们要取走的。我们每一次移动右边界 $i$,将对应的字符 $s[ i] $ 加入到窗口中(也即取走一个字符 $s[ i] $),此时如果 $cnt[ s[ i]] $ 个数小于 $k$,那么我们循环移动左边界 $j$,直到 $cnt[ s[ i]] $ 个数不小于 $k$ 为止。此时的窗口大小为 $i - j + 1$,更新最大窗口。
56
56
57
57
最终的答案就是字符串 $s$ 的长度减去最大窗口的大小。
58
58
59
- 时间复杂度 $O(n)$,空间复杂度 $O(1)$。 其中 $n$ 为字符串 $s$ 的长度。
59
+ 时间复杂度 $O(n)$,其中 $n$ 为字符串 $s$ 的长度。空间复杂度 $O(1)$ 。
60
60
61
61
<!-- tabs:start -->
62
62
@@ -66,14 +66,14 @@ class Solution:
66
66
cnt = Counter(s)
67
67
if any (cnt[c] < k for c in " abc" ):
68
68
return - 1
69
- ans = j = 0
69
+ mx = j = 0
70
70
for i, c in enumerate (s):
71
71
cnt[c] -= 1
72
72
while cnt[c] < k:
73
73
cnt[s[j]] += 1
74
74
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
77
77
```
78
78
79
79
``` java
@@ -84,19 +84,21 @@ class Solution {
84
84
for (int i = 0 ; i < n; ++ i) {
85
85
++ cnt[s. charAt(i) - ' a' ];
86
86
}
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
+ }
89
91
}
90
- int ans = 0 , j = 0 ;
92
+ int mx = 0 , j = 0 ;
91
93
for (int i = 0 ; i < n; ++ i) {
92
94
int c = s. charAt(i) - ' a' ;
93
95
-- cnt[c];
94
96
while (cnt[c] < k) {
95
97
++ cnt[s. charAt(j++ ) - ' a' ];
96
98
}
97
- ans = Math . max(ans , i - j + 1 );
99
+ mx = Math . max(mx , i - j + 1 );
98
100
}
99
- return n - ans ;
101
+ return n - mx ;
100
102
}
101
103
}
102
104
```
@@ -105,20 +107,26 @@ class Solution {
105
107
class Solution {
106
108
public:
107
109
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;
113
121
for (int i = 0; i < n; ++i) {
114
122
int c = s[ i] - 'a';
115
123
--cnt[ c] ;
116
124
while (cnt[ c] < k) {
117
125
++cnt[ s[ j++] - 'a'] ;
118
126
}
119
- ans = max(ans , i - j + 1);
127
+ mx = max(mx , i - j + 1);
120
128
}
121
- return n - ans ;
129
+ return n - mx ;
122
130
}
123
131
};
124
132
```
@@ -129,70 +137,74 @@ func takeCharacters(s string, k int) int {
129
137
for _, c := range s {
130
138
cnt[c-'a']++
131
139
}
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
+ }
134
144
}
135
- ans , j := 0, 0
145
+ mx , j := 0, 0
136
146
for i, c := range s {
137
147
c -= 'a'
138
- cnt[c]--
139
- for cnt[c] < k {
148
+ for cnt[c]--; cnt[c] < k; j++ {
140
149
cnt[s[j]-'a']++
141
- j++
142
150
}
143
- ans = max(ans , i-j+1)
151
+ mx = max(mx , i-j+1)
144
152
}
145
- return len(s) - ans
153
+ return len(s) - mx
146
154
}
147
155
```
148
156
149
157
``` ts
150
158
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 ) ;
153
161
for (const c of s ) {
154
- count [ getIndex (c )]++ ;
162
+ ++ cnt [ idx (c )];
155
163
}
156
- if (count .some (v => v < k )) {
164
+ if (cnt .some (v => v < k )) {
157
165
return - 1 ;
158
166
}
159
167
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 ++ ])] ;
166
174
}
167
- ans = Math .max (ans , j - i + 1 );
175
+ mx = Math .max (mx , i - j + 1 );
168
176
}
169
- return n - ans ;
177
+ return n - mx ;
170
178
}
171
179
```
172
180
173
181
``` rust
182
+ use std :: collections :: HashMap ;
183
+
174
184
impl Solution {
175
185
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 ;
180
189
}
181
- if count . iter (). any (| v | * v < k ) {
190
+
191
+ if " abc" . chars (). any (| c | cnt . get (& c ). unwrap_or (& 0 ) < & k ) {
182
192
return - 1 ;
183
193
}
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 ;
192
204
}
193
- ans = ans . max (j - i + 1 );
205
+ mx = mx . max (i - j + 1 );
194
206
}
195
- (n - ans ) as i32
207
+ (cs . len () as i32 ) - ( mx as i32 )
196
208
}
197
209
}
198
210
```
0 commit comments