最长子串、滑动窗口

这篇博客探讨了如何使用滑动窗口解决两个编程问题:寻找无重复字符的最长子串和找到最大连续1的个数。在第一个问题中,通过滑动窗口优化了暴力搜索,减少了重复计算。在第二个问题中,滑动窗口被用来跟踪和更新满足条件的最长子数组。这两种解法都展示了滑动窗口在处理数组和字符串问题时的有效性。
摘要由CSDN通过智能技术生成

最长子串与滑动窗口

例题 力扣: 无重复字符的最长子串

题目描述:给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

题解

暴力法与滑动窗口:
1、暴力法:遍历字符串,依次以每一个字符当做子串的头,找到当前字符作为子串头的最长子串。采用双重循环,外循环遍历字符串,内循环搜索当前不重复的最大子串。(仔细观察发现,每一个以当前字符作为头的最长子串与前一个字符为头的最长子串之间有重叠部分,抓住这个特点,提高效率)
2、滑动窗口:引入队列,记录以当前字符作为子串的头最大不重复子串。提高效率的地方在于:充分利用上一个最大不重复子串与当前最大不重复子串的“重叠部分”。
具体操作方法:比如例题中的 abcabcbb,窗口的右边界依次向右移动(窗口中的字符串满足要求时左边界保持不动)。右边界移到c处时,窗口中abc 满足要求,当再进入 a,变成了 abca,这时候不满足要求。此时要改变窗口以满足要求:将窗口的左边界向右移动,直到符合要求(将冲突元素移除窗口:bca)。可以把窗口用队列比较容易实现。

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int maxlen=0;
        unordered_set<char> tems;//窗口中的字符串
        int len=s.length();
        int left=0,right=0;
        while(left<len&&right<len)
        {
            if(tems.find(s[right])==tems.end())//s[right]与窗口中的子串不冲突
            {
                tems.insert(s[right++]);
            }
            else//有重复时
            {
               do{
                   tems.erase(s[left]);
                   left++;
               }while(tems.find(s[right])!=tems.end());//移动窗口左边界直至满足要求
            }
     
           maxlen=max(maxlen,int(tems.size()));
        }
        return maxlen;
    }
};

例题2力扣1004最大连续1的个数

给定一个由若干 0 和 1 组成的数组 A,我们最多可以将 K 个值从 0 变成 1 。
返回仅包含 1 的最长(连续)子数组的长度。
示例 1:
输入:A = [1,1,1,0,0,0,1,1,1,1,0], K = 2
输出:6
解释: 
[1,1,1,0,0,1,1,1,1,1,1]
粗体数字从 0 翻转到 1,最长的子数组长度为 6。

解法:

class Solution {
public:
    int longestOnes(vector<int>& nums, int k) {
        int countR=0;
        int start=0,end=0;
        int len=nums.size();
        // int maxlen=0;
        while(end<len&&start<len)
        {
            //解法一       
            // if(nums[end]==0)
            // {
            //     // countRi.push_back(end);
            //     countR++;
            // }
            // end++;
            // while(countR>k)
            // {
            //     // start=countRi.front()+1;
            //     // countRi.pop_front();
            //     if(nums[start++]==0)
            //         countR--;
            // }
            // maxlen=max(maxlen,end-start);
          //解法二:滑动窗口的平移与扩张思想。
            if(nums[end++]==0)
            {
                countR++;
            }
            if(countR>k)//当count<=k时扩张(左边界不动,右边界+1)
            //当countR>k时,左边界+1,右边界+1相当于平移窗口。
            //时刻保持以当前符合要求的最大窗口搜索
            {
                if(nums[start++]==0)
                {
                    countR--;
                }
            }
        }
        return end-start;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嗯哼_Hello

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值