《滑动窗口》定长滑动窗口

1. LeetCode 1456 定长子串中元音的最大数目

方法1:滑动窗口

class Solution {
    public int maxVowels(String s, int k) {
        int n = s.length(), count = 0, ans = 0;
        for (int i = 0; i < n; i++) {
            count += isVowel(s.charAt(i));
            if (i >= k) {
                count -= isVowel(s.charAt(i - k));
            }
            ans = Math.max(count, ans); // count在开始阶段单调不减
        }
        return ans;
    }

    public int isVowel(char ch) {
        return ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u' ? 1 : 0;
    }
}
class Solution:
    def maxVowels(self, s: str, k: int) -> int:
        count = 0; ans = 0
        for i, ch in enumerate(s):
            count += 1 if ch in "aeiou" else 0
            if i >= k:
                count -= 1 if s[i - k] in "aeiou" else 0
            ans = max(ans, count) # count在开始阶段单调不减
        return ans

2. LeetCode 1984 学生分数的最小差值

方法1:排序 + 滑动窗口

class Solution {
    public int minimumDifference(int[] nums, int k) {
        Arrays.sort(nums);
        int n = nums.length, ans = 1_000_00;
        for (int i = 0; i < n - k + 1; i++)
            ans = Math.min(ans, nums[i + k - 1] - nums[i]);
        return ans;
    }
}
class Solution:
    def minimumDifference(self, nums: List[int], k: int) -> int:
        nums.sort(); ans = 1_000_00
        for i in range(len(nums) - k + 1):
            ans = min(ans, nums[i + k - 1] - nums[i])
        return ans

3. LeetCode 643 子数组最大平均数I

方法1:滑动窗口 + 思维

class Solution {
    public double findMaxAverage(int[] nums, int k) {
        int n = nums.length, val = 0;
        for (int i = 0 ; i < k; i++) 
            val += nums[i];
        int ans = val; // 本题存在负数需要先记录开始阶段的和
        for (int i = k; i < n; i++) {
            val += nums[i] - nums[i - k];
            ans = Math.max(ans, val);
        }
        return 1.0 * ans / k;
    }
}
class Solution:
    def findMaxAverage(self, nums: List[int], k: int) -> float:
        ans = val = sum(nums[ : k]) # 本题存在负数需要先记录开始阶段的和
        for i in range(k, len(nums)):
            val += nums[i] - nums[i - k]
            ans = max(ans, val)
        return ans / k

4. LeetCode 1343 大小为K且平均值大于等于阈值的子数组数目

方法1:滑动窗口

class Solution {
    public int numOfSubarrays(int[] arr, int k, int threshold) {
        int n = arr.length, val = 0;
        for (int i = 0; i < k; i++) 
            val += arr[i];
        int ans = val >= k * threshold ? 1 : 0;
        for (int i = k; i < n; i++) {
            val += arr[i] - arr[i - k];
            ans += val >= k * threshold ? 1 : 0;
        }
        return ans;
    }
}
class Solution:
    def numOfSubarrays(self, arr: List[int], k: int, threshold: int) -> int:
        val = sum(arr[ : k])
        ans = 1 if val >= k * threshold else 0 
        for i in range(k, len(arr)):
            val += arr[i] - arr[i - k]
            ans += 1 if val >= k * threshold else 0
        return ans

5. LeetCode 2090 半径为k的子数组平均值

方法1:滑动窗口

class Solution {
    public int[] getAverages(int[] nums, int k) {
        int n = nums.length;
        int[] ans = new int[n];
        Arrays.fill(ans, -1);
        if (2 * k + 1 <= n) {
            long val = 0; // 防止溢出
            for (int i = 0; i < 2 * k; i++)
                val += nums[i];
            for (int i = k; i < n - k; i++) { // 遍历中心位置
                val += nums[i + k];
                ans[i] = (int)(val / (2 * k + 1));
                val -= nums[i - k];
            }
        }
        return ans;
    }
}
class Solution:
    def getAverages(self, nums: List[int], k: int) -> List[int]:
        n = len(nums); ans = [-1] * n
        if 2 * k + 1 <= n:
            val = sum(nums[ : 2 * k])
            for i in range(k, n - k): # 遍历中心位置
                val += nums[i + k]
                ans[i] = val // (2 * k + 1)
                val -= nums[i - k]
        return ans

6. LeetCode 2379 得到K个黑块的最少涂色次数

方法1:滑动窗口 + 思维

class Solution {
    public int minimumRecolors(String blocks, int k) {
        int n = blocks.length(), count = 0, ans = 0;
        for (int i = 0; i < n; i++) {
            count += blocks.charAt(i) == 'B' ? 1 : 0;
            if (i >= k)
                count -= blocks.charAt(i - k) == 'B' ? 1 : 0;
            ans = Math.max(ans, count);
        }
        return Math.max(0, k - ans);
    }
}
class Solution:
    def minimumRecolors(self, blocks: str, k: int) -> int:
        ans = val = 0
        for i, ch in enumerate(blocks):
            val += 1 if ch == 'B' else 0
            if i >= k:
                val -= 1 if blocks[i - k] == 'B' else 0
            ans = max(ans, val)
        return max(0, k - ans)

7. LeetCode 1052 爱生气的书店老板

方法1:滑动窗口 + 思维

class Solution {
    public int maxSatisfied(int[] customers, int[] grumpy, int minutes) {
        // cnt 记录定长区间生气人数 tol 记录非生气总人数
        int n = customers.length, cnt = 0, ans = 0, tol = 0;
        for (int i = 0; i < n; i++) {
            tol += grumpy[i] == 0 ? customers[i] : 0;
            cnt += grumpy[i] == 1 ? customers[i] : 0;
            if (i >= minutes) 
                cnt -= grumpy[i - minutes] == 1 ? customers[i - minutes] : 0;
            ans = Math.max(ans, cnt);
        }
        return tol + ans;
    }
}
class Solution:
    def maxSatisfied(self, customers: List[int], grumpy: List[int], minutes: int) -> int:
        n = len(customers); tol, cnt, ans = 0, 0, 0
        for i in range(n):
            tol += customers[i] if grumpy[i] == 0 else 0
            cnt += customers[i] if grumpy[i] == 1 else 0
            if i >= minutes:
                cnt -= customers[i - minutes] if grumpy[i - minutes] == 1 else 0
            ans = max(ans, cnt)
        return tol + ans

8. LeetCode 2841 几乎唯一子数组的最大和

方法1:滑动窗口 + 哈希表

class Solution {
    public long maxSum(List<Integer> nums, int m, int k) {
        int n = nums.size();
        long val = 0; // 防止溢出
        HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
        for (int i = 0; i < k; i++) {
            val += nums.get(i);
            map.merge(nums.get(i), 1, Integer::sum);
        }
        long ans = map.size() >= m ? val : 0;
        for (int i = k; i < n; i++) {
            val += nums.get(i) - nums.get(i - k);
            map.merge(nums.get(i), 1, Integer::sum); // 将该元素加入字典中
            // merge 会返回计算后的结果
            if (map.merge(nums.get(i - k), -1, Integer::sum) == 0)
                map.remove(nums.get(i - k));
            if (map.size() >= m)
                ans = Math.max(ans, val);
        }
        return ans;
    }
}
class Solution:
    def maxSum(self, nums: List[int], m: int, k: int) -> int:
        n = len(nums); val = sum(nums[ : k])
        cnt = Counter(nums[ : k]) # python 计数字典
        ans = val if len(cnt) >= m else 0
        for i in range(k, n):
            val += nums[i] - nums[i - k]
            cnt[nums[i]] += 1 # 加入元素
            cnt[nums[i - k]] -= 1 # 删除元素
            if cnt[nums[i - k]] == 0:
                del cnt[nums[i - k]]
            if len(cnt) >= m:
                ans = max(ans, val)
        return ans

9. LeetCode 2461 长度为K子数组中的最大和

方法1:滑动窗口 + 标记数组

class Solution {
    public long maximumSubarraySum(int[] nums, int k) {
        int MX = 1_000_00;
        int[] vis = new int[MX + 1];
        // cnt 记录当前区间存在多少不同数字
        int n = nums.length, cnt = 0;
        long val = 0; // 防止溢出
        for (int i = 0; i < k; i++) {
            val += nums[i];
            cnt += vis[nums[i]] == 0 ? 1 : 0;
            vis[nums[i]]++;
        }
        long ans = cnt == k ? val : 0;
        for (int i = k; i < n; i++) {
            val += nums[i] - nums[i - k];
            // 加入 nums[i] 产生的变化
            cnt += vis[nums[i]] == 0 ? 1 : 0;
            vis[nums[i]]++;
            // 删除 nums[i - k] 产生的变化
            vis[nums[i - k]]--;
            cnt -= vis[nums[i - k]] == 0 ? 1 : 0;
            if (cnt == k)
                ans = Math.max(ans, val);
        }
        return ans;
    }
}
class Solution:
    def maximumSubarraySum(self, nums: List[int], k: int) -> int:
        vis = [0] * (1_000_00 + 1)
        cnt, val, ans = 0, 0, 0
        for i in range(len(nums)):
            val += nums[i] # 加入元素
            cnt += 1 if vis[nums[i]] == 0 else 0
            vis[nums[i]] += 1
            if i >= k:
                val -= nums[i - k] # 删除元素
                vis[nums[i - k]] -= 1
                cnt -= 1 if vis[nums[i - k]] == 0 else 0
            ans = max(ans, val) if cnt == k else ans
        return ans

10. LeetCode 1423 可获得的最大点数

方法1:滑动窗口 + 思维

class Solution {
    public int maxScore(int[] cardPoints, int k) {
        // 从 k-1 到 0 再从 n-1 到 n-k 滑动
        int n = cardPoints.length, val = 0;
        for (int i = n - k; i < n; i++)
            val += cardPoints[i];
        int ans = val;
        for (int i = 0; i < k; i++) {
            val += cardPoints[i] - cardPoints[n - k + i];
            ans = Math.max(ans, val);
        }
        return ans;
    }
}
class Solution:
    def maxScore(self, cardPoints: List[int], k: int) -> int:
        ans = val = sum(cardPoints[-k : ])
        for i in range(k):
            val += cardPoints[i] - cardPoints[-k + i]
            ans = max(ans, val)
        return ans

11. LeetCode 2134 最少交换次数来组合所有的1 II

方法1:滑动窗口 + 思维

class Solution {
    public int minSwaps(int[] nums) {
        int n = nums.length, cnt1 = 0;
        for (int i = 0; i < n; i++) 
            cnt1 += nums[i]; // 定区间长度 cnt1
        int ans = 0, val = 0; // val 为 1 的个数
        for (int i = 0; i < n - 1 + cnt1; i++) { // 可以循环
            val += nums[i % n];
            if (i >= cnt1)
                val -= nums[i - cnt1];
            ans = Math.max(ans, val);
        }
        return cnt1 - ans;
    }
}
class Solution:
    def minSwaps(self, nums: List[int]) -> int:
        n = len(nums); cnt = sum(nums) # 1 的个数
        ans = val = 0
        for i in range(n - 1 + cnt):
            val += nums[i % n]
            if i >= cnt:
                val -= nums[i - cnt]
            ans = max(ans, val)
        return cnt - ans

12. LeetCode 567 字符串的排列

13. LeetCode 438 找到字符串中所有字母异位词

14. LeetCode 2156 查找给定哈希值的子串

15. LeetCode 2953 统计完全子字符串

posted @   Koonan-Edogawa  阅读(16)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示