滑动窗口一题


今天参加了一下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
}

Author: 蒋璋
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint polocy. If reproduced, please indicate source 蒋璋 !