坚持内卷
209. 长度最小的子数组
给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
示例 1:
输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。
所谓滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。
在right循环里,left++
我的做法:
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int left = 0,right = 0, sub = 0,sum = 0,result = Integer.MAX_VALUE;
for(right = 0;right <nums.length; right ++){
sum +=nums[right];
while(sum >= target){
sub = right -left +1;
result = result < sub ?result :sub;
sum -= nums[left++];
}
}
return result == Integer.MAX_VALUE? 0 :result;
}
}
不要以为for里放一个while就以为是O(n^2)啊, 主要是看每一个元素被操作的次数,每个元素在滑动窗后进来操作一次,出去操作一次,每个元素都是被被操作两次,所以时间复杂度是 2 × n 也就是O(n)。
904. 水果成篮 中等题
这里有坑,数不大于数组的数量
1 <= fruits.length <= 105
0 <= fruits[i] < fruits.length
class Solution {
public int totalFruit(int[] fruits) {
int left= 0,right = 0,count = 0;
int [] i = new int[fruits.length];
int total = 0;
if(fruits.length <=2){
return fruits.length;
}
for(right =0; right <fruits.length;right ++){
i[fruits[right]] +=1;
if(i[fruits[right]] == 1) count++;
while(count > 2){ //这里是while 而不是if
i[fruits[left]] -=1;
if(i[fruits[left]] == 0) count--;
left++;
}
total = total >(right -left +1) ? total : (right -left +1);
}
return total;
}
}
76. 最小覆盖子串
滑动窗口的思想:
用i,j表示滑动窗口的左边界和右边界,通过改变i,j来扩展和收缩滑动窗口,可以想象成一个窗口在字符串上游走,当这个窗口包含的元素满足条件,即包含字符串T的所有元素,记录下这个滑动窗口的长度j-i+1,这些长度中的最小值就是要求的结果。
步骤一
不断增加j使滑动窗口增大,直到窗口包含了T的所有元素
步骤二
不断增加i使滑动窗口缩小,因为是要求最小字串,所以将不必要的元素排除在外,使长度减小,直到碰到一个必须包含的元素,这个时候不能再扔了,再扔就不满足条件了,记录此时滑动窗口的长度,并保存最小值
步骤三
让i再增加一个位置,这个时候滑动窗口肯定不满足条件了,那么继续从步骤一开始执行,寻找新的满足条件的滑动窗口,如此反复,直到j超出了字符串S范围。
class Solution {
public String minWindow(String s, String t) {
if(s =="" || s.length() == 0 || t == "" || t.length() == 0)
return "";
int left = 0,right = 0, count = t.length(),size =Integer.MAX_VALUE,start =0;
int [] need = new int[128];
for( int i = 0; i<t.length();i++){
need[t.charAt(i)] ++;
}
while(right <s.length()){
char c= s.charAt(right);
if(need[c] >0){
count--;
}
need[c]--;
if(count ==0){
while(left < right && need[s.charAt(left)] <0){
need[s.charAt(left)]++;
left++;
}
if(size>(right -left +1)){
size = right-left +1;
start = left;
}
need[s.charAt(left)]++;
left++;
count++;
}
right++;
}
return size ==Integer.MAX_VALUE ? "" :s.substring(start,start+size);
}
}