ray-note/LeetCode 刷题笔记.md

142 lines
4.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

- [3137. K 周期字符串需要的最少操作次数](https://leetcode.cn/problems/minimum-number-of-operations-to-make-word-k-periodic/description/?envType=daily-question&envId=2024-08-17)
- 按照 k 长度进行字符串分割
- 把分割的子串做为hashmap的key计算不同的key计数
- 用总的子串数 - 最多计数的子串数
### 411 周赛
- [100402. 统计满足 K 约束的子字符串数量 I - 力扣LeetCode](https://leetcode.cn/problems/count-substrings-that-satisfy-k-constraint-i/description/)
- 使用暴力dp
计算 i-j 的 01 的数量,通过计算 i-j 之前的子串数量,再求和。最后得到的答案
- 使用滑动窗口
```rust
impl Solution {
pub fn count_k_constraint_substrings(s: String, k: i32) -> i32 {
let mut ans: i32 = 0;
let mut left = 0;
let mut cnt = [0; 2];
let chars = s.chars().collect::<Vec<char>>();
for (right, ch) in chars.iter().enumerate() {
// 计算当前窗口的 '0' '1' 的数量
cnt[ch.to_digit(10).unwrap() as usize] += 1;
// 如果窗口内的 '0' '1' 数量不满足条件,则通过 left+=1移动窗口
while cnt[0] > k && cnt[1] > k {
cnt[chars[left].to_digit(10).unwrap() as usize] -= 1;
left += 1;
}
// 把窗口长度加到结果里面,窗口内的符合条件的子串,会被其他窗口添加进去
ans += (right - left + 1) as i32;
}
return ans;
}
}
```
## [3306. 元音辅音字符串计数 II - 力扣LeetCode](https://leetcode.cn/problems/count-of-substrings-containing-every-vowel-and-k-consonants-ii/description/)
```Rust
use std::collections::HashMap;
impl Solution {
pub fn count_of_substrings(word: String, k: i32) -> i64 {
let len = word.len();
let word_arr = word.chars().collect::<Vec<char>>();
let mut vowel_map: HashMap<char, i32> = HashMap::new();
let mut k_cnt = 0;
fn is_vowel(c: &char) -> bool {
"aeiou".contains(*c)
}
let mut last_next = len;
let mut cache = vec![0; len];
for i in (0..len).rev() {
cache[i] = last_next;
if !is_vowel(&word_arr[i]) {
last_next = i;
}
}
let mut left = 0;
let mut ans = 0;
for right in 0..len {
if is_vowel(&word_arr[right]) {
let e = vowel_map.entry(word_arr[right]).or_insert(0);
*e += 1;
} else {
k_cnt += 1;
}
let val = cache[right] - right;
while (left <= right && k_cnt > k) || (vowel_map.len() == 5 && k_cnt == k) {
if vowel_map.len() == 5 && k_cnt == k {
ans += val as i64;
}
let l_ch = &word_arr[left];
if is_vowel(l_ch) {
let e = vowel_map.entry(*l_ch).or_insert(0);
if *e == 1 { vowel_map.remove(&l_ch); } else { *e -= 1; }
} else {
k_cnt -= 1;
}
left += 1;
}
}
ans
}
}
```
第二种看的大佬的题解把计算k个辅音字母数改成至少 k 个辅音字母数最后可以通过fn(k) - f(k+1) 计算的到复合预期的子字符串的总数, 代码如下:
```Rust
use std::collections::HashMap;
impl Solution {
pub fn count_of_substrings(word: String, k: i32) -> i64 {
fn cal(word: &Vec<char>, k: i32) -> i64 {
let len = word.len();
let mut vowel_map: HashMap<&char, i32> = HashMap::new();
let mut k_cnt = 0;
fn is_vowel(c: &char) -> bool {
"aeiou".contains(*c)
}
let mut left = 0;
let mut ans = 0;
for (i, ch) in word.iter().enumerate() {
if is_vowel(ch) {
let e = vowel_map.entry(ch).or_insert(0);
*e += 1;
} else {
k_cnt += 1;
}
while vowel_map.len() == 5 && k_cnt >= k {
let l_ch = &word[left];
if is_vowel(&l_ch) {
let e = vowel_map.entry(l_ch).or_insert(0);
if *e == 1 { vowel_map.remove(&l_ch); } else { *e -= 1; }
} else {
k_cnt -= 1;
}
left += 1;
}
ans += left as i64;
}
ans
}
let char_arr = word.chars().collect::<Vec<char>>();
cal(&char_arr, k) - cal(&char_arr, k+1)
}
}
```