目录
学了滑动窗口这个算法思想后,给我最大的感悟就是,我们要不断鞭策自己前行,像滑动窗口一样,要不断调整,维护,更新自己这个有巨大潜力的"窗口"!!!不断前行,不断反思,然后不断进步!!
🌿长度最小的子数组
🧊题目链接
https://leetcode.cn/problems/minimum-size-subarray-sum/
🧊题目描述

🧊题目分析

🧊解题代码
java
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int left=0,right=0;
int mix=Integer.MAX_VALUE;//整形int最大值
int sum=0;
for(;right<nums.length;right++){
sum+=nums[right];//进窗口
while(sum>=target){//维护窗
mix=Math.min(mix,right-left+1);//实时更新记录符合条件的最小长度
sum-=nums[left++];
}
}
return mix==Integer.MAX_VALUE?0:mix;//有可能mix没有改变,也就是0这种情况不要漏
}
}
🌿无重复字符的最长子串
🧊题目链接
https://leetcode.cn/problems/longest-substring-without-repeating-characters/
🧊题目描述

🧊题目分析
我们这一个题和前一道题有点不同,虽然都是用到了滑动窗口,但这个题我们需要在每次维护窗口的时候之后,也就是出了维护窗口那个循环后,才更新结果 ,而前一道题,是维护窗口的那个循环里,一开始就更新结果,两者本质区别就是这题维护的是使其窗口合法 ,而前一道题是将合法的窗口维护成不合法的窗口,但在每次维护成不合法的窗口之前,先更新结果,使right能不断右移,达到只要窗口一合法,就更新结果,然后使其维护成不合法的窗口,"驱动"这个窗口不断滑动!!
哈哈,感觉全在将前一道题的知识,反正这两题相互相通,这也就是我为啥要提前一题的根本原因!!
🧊解题代码
java
class Solution {
public int lengthOfLongestSubstring(String s) {
char[] ss=s.toCharArray();//String转char数组的方法
int[] hash=new int[128];//模拟字符的哈希表
int left=0,right=0;
int ret=0;
for(;right<ss.length;right++){
hash[ss[right]]++; //进窗口
while(hash[ss[right]]>1){//维护这个窗口始终不含重复字符
hash[ss[left++]]--;//不符合就代表left那个值无用了,需要left右移
}
ret=Math.max(ret,right-left+1);//一趟下来,我们维护的这个窗口,没有重复字符,此时就需要更新一下结果
}
return ret;
}
}
🌿最大连续1的个数III
🧊题目链接
1004. 最大连续1的个数 III - 力扣(LeetCode)
🧊题目描述

🧊题目分析
这个和上一个题一样,都是维护窗口的合法性,最后才跟更新结果,也是和上一个题思路一致。
🧊解题代码
java
class Solution {
public int longestOnes(int[] nums, int k) {
int left=0,right=0;
int count=0;//统计窗口里0的个数
int ret=0;//记录结果
for(;right<nums.length;right++){
if(nums[right]==0){//维护count
count++;
}
while(count>k){//维护窗口的合法性
if(nums[left]==0){
count--;
}
left++;
}
ret=Math.max(ret,right-left+1);//最后这个窗口就是合法的了,可以进行更新结果
}
return ret;
}
}
🌿将x减到0的最小操作数
🧊题目链接
https://leetcode.cn/problems/minimum-operations-to-reduce-x-to-zero/
🧊题目描述

🧊题目分析

这个和上一个题一样,都是维护窗口的合法性,最后才跟更新结果 ,也是和上一个题思路一致,但就是运用了**"正难则反"**这个思维
🧊解题代码
java
class Solution {
public int minOperations(int[] nums, int x) {
int target=0;//这个变量用来确定x与之对应的区间
int count=0;//窗口的和
for(int x1:nums){//先计算整个数组的和
target+=x1;
}
target-=x;//然后最终确定好
if(target<0){//这就是x的值超过整个数组和的值
return -1;//那为啥要额外的拎出来写呢,那就是,在后面while(count>target)判断里,会始终满足,然后对我们
} //的正常的窗口有影响
int max=-1;//记录符合条件的窗口的最大值
int left=0,right=0;
for(;right<nums.length;right++){
count+=nums[right];//进窗口
while(count>target){//出窗口,维护窗口
count -= nums[left++];
}
if(count==target){//在不大于target的情况下,符合题意,那就更新max结果
max=Math.max(max,right-left+1);
}
}
return max==-1?-1:nums.length-max;//要注意下没有符合条件的x,也就是max始终没有改变,还是-1
}
}
🌿水果成蓝
🧊题目链接
https://leetcode.cn/problems/fruit-into-baskets/
🧊题目描述

🧊题目分析


🧊解题代码
java
class Solution {//其实整体代码逻辑不难,主要是看自己对HashMap常用方法熟不熟悉
public int totalFruit(int[] fruits) {
HashMap<Integer,Integer> hash=new HashMap<Integer,Integer>();//用hash表
int left=0,right=0;
int ret=0;//记录收集水果的最大数目
for(;right<fruits.length;right++){
hash.put(fruits[right],hash.getOrDefault(fruits[right],0)+1);//进窗口,增操作
while(hash.size()>2){//维护窗口
if(hash.get(fruits[left])==1){// 减/删 去key对应的value
hash.remove(fruits[left]);
}else{
hash.put(fruits[left],hash.get(fruits[left])-1);
}
left++;
}
if(hash.size()<=2){//符合条件,更新结果
ret=Math.max(ret,right-left+1);
}
}
return ret;
}
}
🌿找到字符串中所有字母异位词
🧊题目链接
https://leetcode.cn/problems/find-all-anagrams-in-a-string/description/
🧊题目描述

🧊题目分析

🧊解题代码
java
class Solution {
public List<Integer> findAnagrams(String s, String p) {
char[] s1=s.toCharArray();//用字符数组好操作些
char[] s2=p.toCharArray();
HashMap<Character,Integer> hash1=new HashMap<>();//表1记录字符串s的字符情况
HashMap<Character,Integer> hash2=new HashMap<>();//表2记录字符串p的字符情况,但要先一次性遍历完
List<Integer> list=new ArrayList<>();//list记录结果
for(int i=0;i<p.length();i++){//先把hash2给记录好
hash2.put(s2[i],hash2.getOrDefault(s2[i],0)+1);
}
int left=0,right=0;
int count1=0;//用于记录有效字符个数,也就是hash2表里存在时,hash1表又要对其增加或删除时,就需要对count1进行维护,这也是后面判断是否是字符串p的字母异位词的关键!
int n=p.length();//这个是字符串p的有效字符个数
for(;right<s1.length;right++){
hash1.put(s1[right],hash1.getOrDefault(s1[right],0)+1);//进窗口,维护hash1表
if(hash1.get(s1[right])<=hash2.getOrDefault(s1[right],0)){//维护完hash1表之后,如果发现hash1对应的right值<=hash2对应的right值,就说明刚刚进入窗口的字符是字符串p的异位词的其中一个有效字符,就需要维护count1
count1++;
}
while((right-left+1)>n){//维护窗口大小
//这里我没简短公共代码,主要是怕以后看不懂,给忘了
//这下面代码就是出窗口+维护hash1表+维护count1
if(hash1.get(s1[left])<=hash2.getOrDefault(s1[left],0)){//为有效字符就维护hash1表+维护count1
if(hash1.get(s1[left])==1){//只剩下一个,那就remove清空
hash1.remove(s1[left]);
}else{//还有不止一个,那就-1
hash1.put(s1[left],hash1.get(s1[left])-1);
}
count1--;
}else{//不是有效字符,就只需要维护hash1表,逻辑和上面代码一致
if(hash1.get(s1[left])==1){
hash1.remove(s1[left]);
}else{
hash1.put(s1[left],hash1.get(s1[left])-1);
}
}
left++;//别忘了,left要更新
}
if(count1==n){//最后count1变量发挥作用,对符合条件的窗口进行add即可
list.add(left);
}
}
return list;
}
}
🌿串联所有单词的子串
🧊题目链接
https://leetcode.cn/problems/substring-with-concatenation-of-all-words/description/
🧊题目描述

🧊题目分析

🧊解题代码
java
class Solution {
public List<Integer> findSubstring(String s, String[] words) {
HashMap<String,Integer> hash1=new HashMap<>();//记录字符串s的进窗口字符串信息
HashMap<String,Integer> hash2=new HashMap<>();//记录字符串数组words的字符串的映射值
for(int i=0;i<words.length;i++){//先把hash2给记录好
hash2.put(words[i],hash2.getOrDefault(words[i],0)+1);
}
List<Integer> list=new ArrayList<>();//list记录结果
int left=0,right=0;
int count1=0;//有效字符串个数
int n=words.length;//有效字符串个数
int onlywords=words[0].length();//words中任意一子串长度计算
for(;right<onlywords;right++){//外层循环,循环onlywords遍
int flag=right;//保留记录原始right值,方便后面重置right值
for(left=right;right+onlywords<=s.length();right+=onlywords){//这个终止条件自己画图理解
hash1.put(s.substring(right,right+onlywords),hash1.getOrDefault(s.substring(right,right+onlywords),0)+1);//进窗口,维护hash1表
if(hash1.get(s.substring(right,right+onlywords))<=hash2.getOrDefault(s.substring(right,right+onlywords),0)){//维护完hash1表之后,如果发现hash1对应的right值<=hash2对应的right值,就说明刚刚进入窗口的字符串是字符串数组words里其中一个有效字符串,就需要维护count1
count1++;
}
while((right-left+onlywords)>(n*onlywords)){
if(hash1.get(s.substring(left,left+onlywords))<=hash2.getOrDefault(s.substring(left,left+onlywords),0)){//为有效字符串就维护hash1表+维护count1
if(hash1.get(s.substring(left,left+onlywords))==1){//只剩下一个,那就remove清空
hash1.remove(s.substring(left,left+onlywords));
}else{//还有不止一个,那就-1
hash1.put(s.substring(left,left+onlywords),hash1.get(s.substring(left,left+onlywords))-1);
}
count1--;
}else{//不是有效字符串,就只需要维护hash1表,逻辑和上面代码一致
if(hash1.get(s.substring(left,left+onlywords))==1){
hash1.remove(s.substring(left,left+onlywords));
}else{
hash1.put(s.substring(left,left+onlywords),hash1.get(s.substring(left,left+onlywords))-1);
}
}
left+=onlywords;//别忘了,left要更新,是走一个字符串的长度,也就是onlywords
}
if(count1==n){//最后count1变量发挥作用,对符合条件的窗口进行add即可
list.add(left);
}
}
hash1.clear();//一遍内循环走完,需要情况hash1表
count1=0;//情况hash1表里对应的有效字符串的个数
right=flag;//重置right值
}
return list;
}
}
🌿最小覆盖子串
🧊题目链接
https://leetcode.cn/problems/minimum-window-substring/description/
🧊题目描述

🧊题目分析

🧊解题代码
java
class Solution {
public String minWindow(String s, String t) {
char[] s1=s.toCharArray();
char[] t1=t.toCharArray();
HashMap<Character,Integer> hash1=new HashMap<>();
HashMap<Character,Integer> hash2=new HashMap<>();//计算t字符串个数的映射值
for(int i=0;i<t1.length;i++){//先把hash2给记录好
hash2.put(t1[i],hash2.getOrDefault(t1[i],0)+1);
}
int left=0,right=0;
int count=0;
int min=Integer.MAX_VALUE;//先取整形int的最大值,因为找最小嘛
int lastleft=-1;//-1对后面有帮助
for(;right<s1.length;right++){
hash1.put(s1[right],hash1.getOrDefault(s1[right],0)+1);//进窗口
if(hash1.get(s1[right])<=hash2.getOrDefault(s1[right],0)){//维护有效字符个数count,超过了就不更新count了,反正多多益善嘛哈哈
count++;
}
while(count==t1.length){//一当符合题意区间有了,就更新结果,并试图去寻找最短区间
if((right-left+1)<min){//比原来的区间还小,那就更新结果
lastleft=left;
min=right-left+1;
}
if(hash1.get(s1[left])<=hash2.getOrDefault(s1[left],0)){//属于有效字符个数,出窗口会少个有效字符个数,所以需要维护count
if(hash1.get(s1[left])==1){//维护hash1
表的映射关系
hash1.remove(s1[left]);
}else{//维护hash1
表的映射关系
hash1.put(s1[left],hash1.get(s1[left])-1);
}
count--;//维护count
}else{//不属于有效字符个数,出窗口不会减少有效字符个数,所以不需要维护count
if(hash1.get(s1[left])==1){
hash1.remove(s1[left]);
}else{
hash1.put(s1[left],hash1.get(s1[left])-1);
}
}
left++;//最后逻辑完了,缩短区间
}
}
if(lastleft==-1){//lastleft还有初始值的-1,那就啥也没有最小覆盖子串这一说法,就是count始终达不到有效字符个数啊
return new String();
}
return s.substring(lastleft,lastleft+min);
}
}
完结喽🔎🌿🧊