算法入门---专题二:滑动窗口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计数器的作用是指针在 走的过程中遇到numsptr==1,直接走++到下一个位置,遇到numsptr==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;
    }
    
};
相关推荐
浪客灿心15 分钟前
项目篇:模块设计与实现
数据库·c++
牛油果子哥q28 分钟前
【C++ STL vector】C++ STL vector 终极精讲:动态数组底层原理、两倍扩容机制、迭代器失效、增删查改、性能剖析与工程避坑指南
开发语言·c++
happymaker06261 小时前
LeetCodeHot100——42.接雨水
算法
阿正的梦工坊2 小时前
【Rust】07-错误处理:Option、Result 与 ? 运算符
开发语言·算法·rust
烬羽2 小时前
从零理解树与二叉树:用 JS 带你手撕遍历和递归
javascript·数据结构
YHL2 小时前
🚀从零理解树与二叉树 —— 概念、实现与遍历
前端·javascript·数据结构
为何创造硅基生物2 小时前
独占指针的创建std::make_unique 本身自带堆出现
c++
JieE2123 小时前
JS 到底有多少种数据类型?从ECMA规范到内存本质,一文彻底搞懂
javascript·数据结构·面试
kyle~3 小时前
ROS 2 与 Isaac Sim 联合仿真(一)体系架构、环境选型与基础通信闭环
c++·机器人·nvidia·仿真·ros2
努力努力再努力wz3 小时前
【内存管理与高并发内存池系列】从 mmap 到 malloc:文件映射、匿名映射与 glibc 内存分配机制详解
linux·c语言·数据结构·数据库·c++·qt·链表