滑动窗口算法

将多循环问题改编为单循环问题把O(n2)->变成O(n)

滑动窗口为非就是一进二出三算:
滑动窗口算法分为两种
1.是将多余的部分remove掉
2.仅仅是移动left的值用于回复整个窗口的大小
//滑动窗口算法之一,定窗口
public int lengthOfLongestSubstringKd(String s,int k){
Map<Character,Integer> map = new HashMap();//map是一个窗口,窗口中存放着有用的数据,没用的数据会被抛弃
int left = 0,res = 0;
//res是窗口要算的东西,比如窗口大小或者窗口内部最大值什么的
for(int i = 0;i < s.length();i++){//字符串函数
char cur = s.charAt(i);//取得每一位的数值
map.put(cur,map.getOrDefault(cur,0) + 1);//如果这个数值没被存,那就存进去
// ,v是1,如果这个数已经有了,那就把V加1
while (map.size() > k){//长度指定,当长度满了的时候
char c = s.charAt(left);//取出最左边的数
map.put(c,map.getOrDefault(c,0) - 1);//拿到窗口最左边的数
//将数据的值减一
if(map.get(c) == 0){
map.remove(c);
left++;//将窗口中不符合条件的数据清理出去
}
}
res = Math.max(res,i - left + 1);//算窗口大小
}
return res;
}
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
整个算法结构很简单
1.将所有数据放进map里,无论什么数据都放进map里,值是key,坐标是value
2.当遇到map里有重复时候,移动left到发生重复位置 + 1,相当于将重复部分统统丢弃掉
3.使用 i - left + 1来统计每次循环结束后,窗口内数据长度,通过
res = Math.max(res,i - left + 1)时刻监视窗口长度
4.由于我们只是移动了left长度,相当于只是通过记录方式记录卡点窗口,所以之前被丢弃的部分,并没有被实际上丢掉,只是做了个记号,以前没丢掉的重复部分,会成为影响因素,所以加一层保险
left = Math.max(left,map.get(s.charAt(i)) + 1)
left记号,绝对不可以往前滑动,因为前面都是被抛弃掉了
public static int lengthOfLongestSubstring(String s) {
if (s.length()==0) return 0;
HashMap<Character, Integer> map = new HashMap<Character, Integer>();
int max = 0;
int left = 0;
for(int i = 0; i < s.length(); i ++){
char c = s.charAt(i);
if(map.containsKey(c)){
left = Math.max(left,map.get(s.charAt(i)) + 1);
//这里加1表示,发生重复部分之前的都被抛弃了
}
map.put(s.charAt(i),i);
max = Math.max(max,i-left+1);
}
return max;
}
如图所示
遇到重复部分,就跳到第一次出重复地方的后一位,将之前字符串全部舍弃,消除自己的黑历史,将黑历史干掉。

直接将窗口中有问题的部分,也就是黑历史直接清楚,使用set,将黑历史处理了,全部除掉
class Solution {
public int lengthOfLongestSubstring(String s) {
Set<Character> set = new HashSet();//作为窗口
int res = 0;
int left = 0;
int right = 0;//右边指针
while(right < s.length()){
char c = s.charAt(right++);
if(set.contains(c)){//遇到重复
while(set.contains(c)){
set.remove(s.charAt(left++));//将前面有问题的序列全部从窗口中删除
//让窗口变成真正的窗口,同时让Left不断增加,
}
}
set.add(c);
res = Math.max(res,right - left);
}
return res;
}
}
哥哥自己写的
问题点就是
while判断那,不要用left <= map.get©,因为map在减少!!!当Map没有的时候,map.get©就空指异常了
public static int lengthOfLongestSubstring(String s) {
HashMap<Character, Integer> map = new HashMap<Character, Integer>();
int max = 0;
int left = 0;
for(int i = 0; i < s.length(); i ++){
char c = s.charAt(i);
//进来之前先考察
if(map.containsKey(c)){
int m = map.get(c);
while(left <= m){//定位到出问题的地方
map.remove(s.charAt(left));
left++;//将有问题的全部移除,同时让左指针移动
}
}
map.put(s.charAt(i),i);
max = Math.max(max,i-left + 1);
}
return max;
}
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)