这是一种降低时间复杂度的技巧。
209. 长度最小的子数组
难度中等
给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
示例 1:
输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int l = 0, r = -1;
int sum = 0;
int res = Integer.MAX_VALUE;
while(l < nums.length){
if(r + 1 < nums.length && sum < target){
// r++;
sum += nums[++r];
}else{
sum -= nums[l++];
// l++;
}
if(sum >= target){
res = Math.min(res, r - l + 1);
}
}
return res == Integer.MAX_VALUE ? 0: res;
}
}
int l = 0, r = -1;滑动窗口的大小,一开始把有边界定义为-1,一开始窗口不包含任何值。
r + 1 < nums.length 为了防止数组越界
和条件的值进行比较。target
比target 小,右边界右移,窗口增加
比tartget 大,左边界右移,窗口缩小
每次及时更新结果,最后返回题目要求的最小值。res = Math.min(res, r - l + 1);
//上面是从左边界遍历,时间ON
//也可以从右边界遍历。看个人习惯。
// 滑动窗口
public int minSubArrayLen(int s, int[] nums) {
int left = 0;
int sum = 0;
int result = Integer.MAX_VALUE;
for (int right = 0; right < nums.length; right++) {
sum += nums[right];
while (sum >= s) {
result = Math.min(result, right - left + 1);
sum -= nums[left++];
}
}
return result == Integer.MAX_VALUE ? 0 : result;
}
3. 无重复字符的最长子串
难度中等6271
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
class Solution {
public int lengthOfLongestSubstring(String s) {
//滑动窗口
int left = 0; int right = -1;
int res = 0;//
int [] flag = new int[256];
while(left < s.length()){
//增加窗口
if(right + 1 < s.length() && flag[s.charAt(right + 1)] == 0){
right++;
flag[s.charAt(right)]++;
}else{
flag[s.charAt(left)]--;
left++;
}
res = Math.max(res, right - left + 1);
}
return res;
}
}
这题,几乎是一个思想。用一个查找表去对照,这里用的是一个数组。
r + 1 < nums.length 为了防止数组越界
判断窗口变换的条件
不包含,右边界右移,窗口增加
包含,左边界右移,窗口缩小
每次及时更新结果,最后返回题目要求的最大值。res = Math.max(res, right - left + 1);