一、答题模板
第一步:根据题目设置变量
例如:数组和sum、最大长度等
第二步:确定窗口开始位置start和结束位置end
第三步:判断条件,两种情况
- 窗口长度固定:以窗口长度为判断依据
- 窗口长度可变:根据题目中的要求判断
第四步:更新变量,两种情况
- 窗口长度固定:start右移,维持窗口长度不变
- 窗口长度可变:start右移,直到窗口符合条件为止
二、力扣题
(1)窗口长度可变
a.元素不能重复
- step1:设置变量,不重复元素,维护变量map,key为不重复字符,value为key出现的最后一次下标
- step2:start从0 开始,循环end
- step3:窗口长度可变,判断条件为map中有没有s.charAt(end)
- step4:map中有,则更新start。再计算最大长度,并将s.charAt(end)放入map中,map中有则覆盖,没有则直接放入
class Solution {
public int lengthOfLongestSubstring(String s) {
Map<Character,Integer> map=new HashMap<>();
int start=0;
int res=0;
for(int end=0;end<s.length();end++){
char c=s.charAt(end);
if(map.containsKey(c)){
start=Math.max(start,map.get(c)+1);
}
res=Math.max(res,end-start+1);
map.put(c,end);
}
return res;
}
}
- step1:设置变量,不重复元素,维护变量map,key为不重复字符,value为key出现的最后一次下标
- step2:start从0 开始,循环end
- step3:窗口长度可变,判断条件为map中有没有nums[end]
- step4:map中有,则更新start。与上题不同的是,本题要维护变量temp,来记录start的位置,便于在更新start的时候,可以从sum中减去temp到start位置的和
class Solution {
public int maximumUniqueSubarray(int[] nums) {
Map<Integer,Integer> map=new HashMap<>();
int start=0;
int sum=0;
int res=0;
for(int end=0;end<nums.length;end++){
if(map.containsKey(nums[end])){
int temp=start;
start=Math.max(start,map.get(nums[end])+1);
while(temp!=start){
sum-=nums[temp++];
}
}
sum+=nums[end];
res=Math.max(sum,res);
map.put(nums[end],end);
}
return res;
}
}
b.和问题
- step1:设置变量,维护变量sum
- step2:start从0 开始,循环end
- step3:窗口长度可变,判断条件为sum与target的比较
- step4:sum>=target,则更新start和res。要找最小的数组长度,所以在满足条件的基础上,尽可能减少长度,更新start和sum。满足条件时才能更新res
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int start=0;
int res=Integer.MAX_VALUE;
int sum=0;
for(int end=0;end<nums.length;end++){
sum+=nums[end];
while(sum>=target){
res=Math.min(res,end-start+1);
sum-=nums[start++];
}
}
return res==Integer.MAX_VALUE?0:res;
}
}
1695. 删除子数组的最大得分
与上题类似,但是要求元素不重复。那么需要维护变量map,并且在更新sum时,需要将更新前的start到更新后的start期间的值都减去。
1208. 尽可能使字符串相等
- step1:设置变量,维护变量sum
- step2:start从0 开始,循环end
- step3:窗口长度可变,判断条件为sum与maxCost的比较
- step4:sum>maxCost,则更新start和sum。要找最大长度,在不满足条件的时,更新start和sum以满足条件。满足条件后,更新res
class Solution {
public int equalSubstring(String s, String t, int maxCost) {
int start=0;
int sum=0;
int res=0;
for(int end=0;end<s.length();end++){
sum+=Math.abs(s.charAt(end)-t.charAt(end));
while(sum>maxCost){
sum-=Math.abs(s.charAt(start)-t.charAt(start));
start++;
}
res=Math.max(res,end-start+1);
}
return res;
}
}
c.其他
- step1:设置变量,维护变量res
- step2:start从0 开始,循环end
- step3:窗口长度可变,循环判断条件为k<0
- step4:先end向前走,直到k<0,start开始收缩,收缩到k>=0,符合条件,再更新res的值
class Solution {
public int longestOnes(int[] nums, int k) {
int start=0;
int res=0;
for(int end=0;end<nums.length;end++){
if(nums[end]==0){
k--;
}
//收缩--》k<0时,左边一直收缩
while(k<0){
if(nums[start]==0) k++;
start++;
}
res=Math.max(end-start+1,res);
}
return res;
}
}
(2)窗口长度固定
- step1:设置变量,维护变量count[]来记录p中出现的字母,以及次数
- step2:start和end都从0 开始,用双指针进行循环。不能像之前用for循环end,因为当count[end]==0时,start开始收缩,与此同时,如果end右移,那么下次循环的长度还维持与本次循环的一样,无法通过end-start-1等于p的长度来判断是否为异位词
- step3:窗口长度固定,判断条件为end-start+1与p.lengtha()的比较
- step4:p中出现s.charAt(end),则更新end和count[],没出现则收缩。再根据长度再做判断
class Solution {
public List<Integer> findAnagrams(String s, String p) {
List<Integer> res=new ArrayList<>();
int start=0,end=0;
int[] count=new int[26];
for(int i=0;i<p.length();i++){
count[p.charAt(i)-'a']++;
}
while(end<s.length()){
if(count[s.charAt(end)-'a']>0){
count[s.charAt(end)-'a']--;
if(end-start+1==p.length()){
res.add(start);
}
end++;
}else{
count[s.charAt(start)-'a']++;
start++;
}
}
return res;
}
}
567. 字符串的排列
与上题类似
class Solution {
public boolean checkInclusion(String s1, String s2) {
int[] count=new int[128];
for(int i=0;i<s1.length();i++){
count[s1.charAt(i)-'a']++;
}
int start=0,end=0;
while(end<s2.length()){
if(count[s2.charAt(end)-'a']>0){
count[s2.charAt(end++)-'a']--;
if(end-start==s1.length()){
return true;
}
}else{
count[s2.charAt(start++)-'a']++;
}
}
return false;
}
}
643. 子数组最大平均数 I
与209题类似
class Solution {
//滑动窗口,固定长度
public double findMaxAverage(int[] nums, int k) {
double sum=0;
int start=0;
double res=Integer.MIN_VALUE;//不能设置为0,因为0和sum/k比较会一直是0,但是sum/k会有小于0的情况
for(int end=0;end<nums.length;end++) {
sum += nums[end];
if (end - start + 1 == k) {
res = Math.max(res, sum/k);
sum-=nums[start++];
}
}
return res;
}
}