今天参加了一下leetcode周赛,遇到一题滑动窗口的,这里稍微记一点思路。
题目的链接是https://leetcode.cn/problems/take-k-of-each-character-from-left-and-right/description/
问题是这样的,在只有abc组成的字符串中,每次只能从最左边或者左右边取字符,使abc每种的数量不能少于给定的k。
本来可以先从左边取字符,直到不能取为止;然后再从右边取字符,把左边那部分刚取的字符退掉多余的。但是好像处理不了一个极端情况,就是有一个刚需的字符在最右边,就找不到一个合适的为止断开,或者说把左边那部分退回去。
然后其实可以把问题转换一下,就是取最长的一段中间的字符,使得abc的长度都不超过counter[ch] - k,这样连续的区间就更好处理了。
贴上rust代码。rust比较烦的地方就在于数组只能用usize访问。
pub fn take_characters(s: String, k: i32) -> i32 {
let mut counter: Vec<i32> = vec![0; 3];
let (mut left, mut right) = (0, 0);
let bytes = s.as_bytes();
bytes.iter().for_each(|&x|{
counter[x as usize - 'a' as usize] += 1;
});
for &ch in "abc".as_bytes() {
if counter[ch as usize - 'a' as usize] < k {
return -1;
}
counter[ch as usize - 'a' as usize] -= k;
}
let check = |counter: &mut Vec<i32>| {
counter[0] >= 0 && counter[1] >= 0 && counter[2] >= 0
};
let mut res = 0;
let n = s.len();
while right < n {
while left < right && !check(&mut counter) {
counter[bytes[left] as usize - 'a' as usize] += 1;
left += 1;
}
counter[bytes[right] as usize - 'a' as usize] -= 1;
right += 1;
if check(&mut counter) {
res = i32::max(res, (right - left) as i32);
}
}
n as i32 - res
}