目录
一、LeetCode:209.长度最小的子数组(Medium)
二、LeetCode:3.无重复字符的最长子串(Medium)
三、LeetCode:1004.最大连续1的个数(Medium)
四、LeetCode:1658.将X减到0的最小操作数 (Medium)
六、LeetCode:438.找到字符串中所有字母异位词(Medium)
前言:
Hello,大家好,我是Go。本文将呈现笔者本人最近在做的滑动窗口算法题。记录一下笔者学习到的题解思路以及附上个人代码,供大家参考及指正。希望对正在学习算法,尤其是滑动窗口算法的同学提供一点帮助。
滑动窗口算法:
滑动窗口算法换言之就是 left 和 right 指针同向运动的双指针算法。当 left 和 right 指针的同向运动,限定出一块 连续的区间,我们可以在区间内维护和更新结果时,此算法就是滑动窗口算法。
俗话说 Talk is cheap. Show me the code。我们话不多说,直接上题让大家亲身感受一下。
实战训练:
一、LeetCode:209.长度最小的子数组(Medium)
思路:
1、 根据题目的描述和实例的展示,我们可以分析出。我们要分析的是nums中一段连续的区间,判断 区间和 >= target 的最小区间。所以我们可以利用滑动窗口算法解决问题。
2、首先定义两个指针 left = 0 ,right = 0,sum = 0(记录窗口内元素的和)。
每次,先将right指针所在位置元素相加。sun += nums[right]。并判断sum是否大于等于target
每当大于等于 target。就代表 [left,right-1] 此区间的元素和满足条件,那么我们就更新结果。并且窗口缩小(出窗口),也就 left++ 去下一个窗口寻找满足条件的区间。
小于target的话,代表区间元素和不满足条件,需要继续扩大窗口,也就是 right++。
拿示例一:【2,3,1,2,4,3】举例。区间内元素为 2 3 1 2 时,sum=8 > target。
此时能满足条件的最小区间便是 2 3 1 2。那么此时以2为基准的窗口已经没用了,那么我们就可以将窗口滑动,以3为基准找到满足条件的最小区间。于是找到 3 1 2 4 这个窗口。循环往复直到 r > nums.length-1
图解:
代码:
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int l = 0,r = 0,n = nums.length,min = n+1,sum=0;
while(r<n){
//进窗口
sum += nums[r];
while(sum>=target){
//判断,更新长度
min = Math.min(min,r-l+1);
//出窗口 窗口向右缩减
sum-=nums[l++];
}
//窗口向右扩张
r++;
}
//如果min大于n 表示没有符合的区间,返回0
return min>n ? 0 : min;
}
}
二、LeetCode:3.无重复字符的最长子串(Medium)
思路:
1、从题目可看出,我们分析的是字符串中,连续的无重复的最长区间,所以便可以想到利用滑动窗口。同时为了保证无重复字符(或者说是每个字符只出现一次),就需要哈希表来记录每个字符出现的次数。保证字符唯一
2、定义 left = 0 , right = 0;每次右端字符ch,进入窗口时,都将其放入哈希表中查看出现的次数。
如果该字符存在过(即哈希表key对应的value>1),就缩小窗口,寻找不存在重复字符的区间。
如果该字符没存在过,则代表此区间无重复字符,更新结果。随后继续扩大窗口
代码:
class Solution {
public int lengthOfLongestSubstring(String s) {
//将字符串转换成字符数组
char[] ss = s.toCharArray();
//使用数组模拟哈希表
int[] hash = new int[128];
int l = 0,r = 0,max =0,n =ss.length;
while(r<n){
//入窗口,并在对应处设置哈希值
hash[ss[r]]++;
//判断
while(hash[ss[r]]>1){
//将左端点的数据删除,并出窗口
hash[ss[l++]]--;
}
max = Math.max(max,r-l+1);
r++;
}
return max;
}
}