算法入门---专题二:滑动窗口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;
    }
    
};
相关推荐
B站_计算机毕业设计之家3 小时前
Spark微博舆情分析系统 情感分析 爬虫 Hadoop和Hive 贴吧数据 双平台 讲解视频 大数据 Hadoop ✅
大数据·hadoop·爬虫·python·数据分析·1024程序员节·舆情分析
兮山与3 小时前
算法18.0
算法
Yupureki3 小时前
从零开始的C++学习生活 15:哈希表的使用和封装unordered_map/set
c语言·数据结构·c++·学习·visual studio·1024程序员节
向阳逐梦3 小时前
嵌入式软件算法之PID闭环控制原理
1024程序员节
忧郁的橙子.3 小时前
Kubernetes Calico 网络故障排查与修复:RBAC 权限问题完整解决记录
1024程序员节
我是华为OD~HR~栗栗呀3 小时前
华为OD-Java面经-21届考研
java·c++·后端·python·华为od·华为·面试
Mr.Jessy3 小时前
JavaScript学习第六天:函数
开发语言·前端·javascript·学习·html·1024程序员节
LEEBELOVED3 小时前
R语言高效数据处理-变量批量统计检验
1024程序员节·r语言高效处理数据
码农多耕地呗3 小时前
力扣543.二叉树的直径(java)(迭代法 and 左右根后序遍历迭代法)
算法·leetcode·职场和发展