问题解析:
以这道题为例子:. - 力扣(LeetCode)找长度最小的子数组,子数组和必须大于条件中的target
暴力解法:左右指针列举出每一种子数组的可能,每种可能去求子数组的和,找到最小的子数组。
时间复杂度:On3 左右指针枚举出所有的子数组需要On2的复杂度,再去求每个子数组组的和,总计为On3的复杂度。
暴力枚举的进阶:利用单调性:左指针在最外层循环从左到右进行遍历,右指针每次从左指针开始求和计算找到第一次满足target的子数组,这个数组就是当前左指针下最短数组(单调性)。左指针遍历完数组就能拿到长度最小的子串。
时间复杂度:On2. 不需要通过左右指针去列举出所有的子数组了。只需要左指针进行遍历,然后在左指针的节点从左到右求和即可。
进阶:滑动窗口解决:计算完以当前起始位置的最小子数组后左指针右移时,右指针不用从左指针的位置开始重新计算和了,直接将左指针右移前的和减去左指针原来的位置就可以得到当前子数组的和,直接进行判断,小于target右指针右移、大于target直接记录当前子数组。(也是利用单调性,因为左指针右移,此时子数组的和是缩减的,那么右指针要么不动就可以满足要么需要右移,不可能往左)。
代码:
int sum = 0;
int minLn = Integer.MAX_VALUE;
int left = 0 , right = 0;
while(right < nums.length) {
sum += nums[right ++]; //进窗口
while(sum >= target) { //判断
minLn = Math.min(minLn , right - left); //更新结果
sum -= nums[left ++];//出窗口
}
}
return minLn == Integer.MAX_VALUE ? 0 : minLn;
题目:
. - 力扣(LeetCode)无重复字符最长子串 ****
. - 力扣(LeetCode)最大连续1的个数。****
*****. - 力扣(LeetCode)在数组的前后取值将目标数减到0的最小步数。
题目要求从数组前面或者后面进行操作得到最小步数,俩段是不连续的,但是我们可以将这个问题进行转换:数组是固定的,数组和是固定的,你从俩边去最少的和固定的数,此时中间连续一段子数组的和也是固定的且是最长的。
怎么求中间子数组要满足的和的值:数组总和减去目标数。
此时就可以使用我们的滑动窗口计算出中间这段子数组的长度进而求出俩边的长度。
. - 力扣(LeetCode)只能采摘俩种水果,求采摘最多的水果数量,要求必须连续:
int[] kinds = new int[fruits.length];//下标表示水果种类,值表示对应水果数量
int kind = 0;//已经采摘的水果种类
int left = 0;
int right = 0;
int maxLen = 0; //最大长度即水果数量
while(right < fruits.length) {
kinds[fruits[right]] ++;
if(kinds[fruits[right]] == 1) kind ++;//如果加之后的值是1说明采摘了新种类
while(kind > 2) {
kinds[fruits[left]] --;
if(kinds[fruits[left]] == 0) kind --;
left ++;
}
maxLen = Math.max(right- left + 1 , maxLen);
right ++;
}
return maxLen;
. - 力扣(LeetCode)找字符串中的所有异位词*******
通过异位词的长度来维护这个窗口。同时维护一个有效字母数量用来确定当前字串是否满足异位词要求。
public List<Integer> findAnagrams(String s, String p) {
//建立p的哈希
int[] model = new int[26];
for(int i= 0;i < p.length();i ++) {
model[p.charAt(i) - 97] ++;
}
int[] hash = new int[26];
int left = 0;
int right = 0;
List<Integer> list = new LinkedList<>();
int integalCount = 0;//合法字符数量
while(right < s.length()) {
//只有model中存在且值大于hash中的值时合法字符数量+1,这样当合法字符数量等于p长度时即为目标子串
hash[s.charAt(right) - 97] ++;
if(hash[s.charAt(right) - 97] <= model[s.charAt(right) - 97]) {
integalCount ++;
}
if(right - left + 1 > p.length()) {
hash[s.charAt(left) - 97] --;
if(hash[s.charAt(left) - 97] < model[s.charAt(left) - 97]) {
integalCount --;
}
left ++;
}
if(integalCount == p.length()) list.add(left);
right ++;
}
return list;
}