算法入门---专题二:滑动窗口2(最大连续1的个数,无重复字符的最长子串 )

🎬 胖咕噜的稞达鸭个人主页
🔥 个人专栏 : 《数据结构《C++初阶高阶》《算法入门》

⛺️技术的杠杆,撬动整个世界!


最大连续1的个数

最大连续1的个数

  1. 题目描述
    数组nums中,给定一个整数k,如果最多翻转k个0,要求返回数组中连续1的最大个数。
    这里我们给定一个示例:【 1,1 , 1 , 0 , 0, 0, 1, 1 , 1, 1, 0】
  2. 算法原理:
    解法一:双指针+暴力枚举+counter计数器
    双指针:定义一个left和right指针,先让left在索引为0的位置,right指针向后走,counter计数器的作用是指针在 走的过程中遇到nums[ptr]==1,直接走++到下一个位置,遇到nums[ptr]==0,要将0放到counter中,当counter中记录的0的个数大于k了,就需要让数组中的0翻转为1,再将【left,right】这段区间里面的1的个数记录入ret中,ret用于存储每一次翻转之后的左右区间中的1的个数,每一次记录了新的左右区间,都要将right-left+1和上一次的ret进行比较,只留下最大的那一个。
    暴力枚举,right走到了一个位置,这个位置的数字是0,但是此时counter中已经有等于k个0了,此时left从原来索引为0的位置,走向索引为1,right要退回去,退到索引为0的位置重新开始,这样属于重复操作了,所以进行优化的办法就是让right不用回退,减少算法的执行复杂度------滑动窗口。来进行优化:解法二

解法二:滑动窗口+counter计数器

解法二作为优化解法一,同样也是定义一个right和left,相对比暴力枚举,在优化的地方:right不用回退,如果找到了counter>k,就让left开始向后走,遇到nums[left]==1,left++向后走不进行操作,遇到nums[left]==0,counter--,删除counter中的0,然后让left走到下一个位置开始新一轮的左右区间(如果left没有走到下一个区间,还是处在left==0的位置,就意味着区间中天然多了一个0)。

总结

如果right遇到的数字等于0,就需要进窗口,如果counter大于k,就需要出窗口,让left向后走,遇到0,计数器中的0要减少一个,最后返回每一次更新的ret的最大值。

cpp 复制代码
class Solution {
public:
    int longestOnes(vector<int>& nums, int k) {
        int ret=0;
        for(int left=0,right=0,counter=0;right<nums.size();right++)
        {
            //进窗口,当right指向的数字等于0就形成了有效的滑动窗口
            if(nums[right]==0)counter++;
            //出窗口,如果counter中的0大于k,那就需要left向后遍历,left指向的数字等于1,不做处理,等于0要counter--,此时left到right的区间内已经多了一个0,left的位置向后++一个位置
            while(counter>k){if(nums[left++]==0) counter--;}//出窗口
            
            ret=max(ret,right-left+1);
        }
        return ret;
    }
};

无重复字符的最长子串

无重复字符的最长子串

  1. 题目解析:

    找出字符串中不含重复字符的最长子串的长度。

  2. 算法原理:

    解法一:暴力枚举

    给定两个指针right,left,left和right从索引为0的位置开始,right先走,将nums[right]计入哈希表中,所以首先要定义一个数组来模拟哈希表,这里我们申请128个空间用来存储right遍历中遇到的字符,每走一步都要检查哈希表中有没有相同的字符出现,哈希表中没有重复的字符出现,right++,如果哈希表中出现了重复的字符,那就说明,需要出窗口,此时让left++,right退回到索引为1的位置,继续开始遍历,解法二:讲解right不用回退。

    解法二:滑动窗口

    right走到的位置出现了哈希表中相同的字符,此时从left到right的前一个位置,算是数组中的一个不含有重复字符的字串。当哈希表中出现了重复的字符,此时left开始向后走,遇到哈希表中重复的符字,就从哈希表中删除,然后再走向下一个位置(不然数组中又多了一个即将重复的字符),此时更新一下ret,从每一段right-left+1的长度和已经有的ret进行比较,谁大谁就当作时新的ret。

总结:

right向后开始遍历,每遇到一个从未出现在哈希表中的字符,就计入哈希表中,进窗口;当哈希表中出现了重复的符字,让left向后遍历,遇到重复出现在哈希表中的字符,就从哈希表中删除,出窗口。

  1. 上代码!
cpp 复制代码
class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        //用数组模拟哈希表
        int hash[128]={0};//申请128个空间,每个空间都初始化为0
        //思路:定义一个left,right从索引为0的位置开始遍历
        //先让right不断向后走
        //寻找哈希表中有没有相同的元素,如果有的就停止,计算从left到right这段区间的长度
        //然后出窗口,left移动到第一个重复的字符的后一个位置,不用再让right走回来
        //一直让right遍历到最后一个位置
        int left=0, right=0 , n=s.size();
        int ret=0;
        while(right<n)
        {
            hash[s[right]]++;//进入窗口
            while(hash[s[right]]>1)//判断统计次数,如果出现次数大于1,就说明重复了
            hash[s[left++]]--;//出窗口,先--,将这个字符从哈希表中删除,再++,left的位置走到一重复位置的下一个位置,继续进入哈希表
            ret=max(ret,right-left+1);//从每一段right-left+1的长度和已经有的ret进行比较,谁大谁就当作时新的ret
            right++;//让下一个元素进入窗口
        }
        return ret;
    }
    
};
相关推荐
吃杠碰小鸡几秒前
高中数学-数列-导数证明
前端·数学·算法
故事不长丨几秒前
C#线程同步:lock、Monitor、Mutex原理+用法+实战全解析
开发语言·算法·c#
long3161 分钟前
Aho-Corasick 模式搜索算法
java·数据结构·spring boot·后端·算法·排序算法
近津薪荼2 分钟前
dfs专题4——二叉树的深搜(验证二叉搜索树)
c++·学习·算法·深度优先
熊文豪10 分钟前
探索CANN ops-nn:高性能哈希算子技术解读
算法·哈希算法·cann
熊猫_豆豆27 分钟前
YOLOP车道检测
人工智能·python·算法
艾莉丝努力练剑42 分钟前
【Linux:文件】Ext系列文件系统(初阶)
大数据·linux·运维·服务器·c++·人工智能·算法
Once_day1 小时前
C++之《程序员自我修养》读书总结(1)
c语言·开发语言·c++·程序员自我修养
Trouvaille ~1 小时前
【Linux】TCP Socket编程实战(一):API详解与单连接Echo Server
linux·运维·服务器·网络·c++·tcp/ip·socket