力扣1004. 最大连续1的个数 III

题目:

给你字符串 s 和整数 k 。

请返回字符串 s 中长度为 k 的单个子字符串中可能包含的最大元音字母数。

英文中的 元音字母 为(a, e, i, o, u)。

 

示例 1:

输入:s = "abciiidef", k = 3
输出:3
解释:子字符串 "iii" 包含 3 个元音字母。
示例 2:

输入:s = "aeiou", k = 2
输出:2
解释:任意长度为 2 的子字符串都包含 2 个元音字母。
示例 3:

输入:s = "leetcode", k = 3
输出:2
解释:"lee"、"eet" 和 "ode" 都包含 2 个元音字母。
示例 4:

输入:s = "rhythms", k = 4
输出:0
解释:字符串 s 中不含任何元音字母。
示例 5:

输入:s = "tryhard", k = 4
输出:1
 

提示:

1 <= s.length <= 10^5
s 由小写英文字母组成
1 <= k <= s.length

 

思路:

zn[i]表示数组下标从0~i中0的个数 

对于数组nums的区间[left, right]而言,只要它包含不超过k个0,我们就可以根据它构造出一段满足要求,且长度为right-left+1的区间。

即:zn[right] - zn[left - 1] <= k 

方法一:二分查找 (zn是一个递增数列)

zn[right] - zn[left - 1] <= k 等价于 zn[left - 1] >= zn[right] - k;

枚举right,对于每一个right寻找第一个大于等于zn[right] - k 的left - 1

 

方法二:滑动窗口

由于zn[right] - k 单调递增,我们就可以使用滑动窗口来实时地维护 left和 right。在right 向右移动的过程中,我们同步移动 left,直到 left 为首个(即最小的)满足 

zn[left - 1] >= zn[right] - k 的位置,此时我们就可以使用此区间对答案进行更新了。

 

 

 

代码:(滑动窗口法)

复制代码
class Solution {
public:
    int longestOnes(vector<int>& nums, int k) {
        int n = nums.size();
        int zn[999999] = {0};
        nums[0] == 0 ? zn[0] = 1 : zn[0] = 0; 
        for(int i = 1; i < n; i++){
            if(nums[i] == 0){
                zn[i] = zn[i - 1] + 1;
            }else{
                zn[i] = zn[i - 1];
            }
        }
        int l = 0, ans = 0;
        for(int r = 0; r < n; r++){
            int tmp;
            if(l - 1 < 0){
                tmp = zn[r];
            }else{
                tmp = zn[r] - zn[l - 1];
            }
            while(tmp > k){
                l++;
                if(l - 1 < 0){
                    tmp = zn[r];
                }else{
                    tmp = zn[r] - zn[l - 1];
                }
            }
            ans = max(ans, r - l + 1);
        }
        return ans;
    }
};
复制代码

 

posted @   Yohoc  阅读(10)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示