Leetcode 209. 长度最小的子数组
问题:给定一个含有 n 个正整数的数组和一个正整数 target 。找出该数组中满足其总和大于等于 target 的长度最小的子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
算法:滑动窗口,左右两个指针,从最左边开始遍历,右指针 right 右移,当子数组的和 sum 满足条件(>= target)时记录长度存入 ans ,然后左指针 left 右移寻找下一个符合条件的子数组。
代码:
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int n = nums.size(),left = 0,sum = 0,ans = n + 1;
for(int right = 0;right< n;right++){
sum += nums[right];//+右面的
while(sum >= target){
ans = min(ans,(right - left + 1));//满足条件,存储长度
sum -= nums[left++];//左指针右移继续找下一个
}
}
return ans <= n ? ans:0;
}
};
Leetcode 713. 乘积小于 K 的子数组
问题:给你一个整数数组 nums 和一个整数 k ,请你返回子数组内所有元素的乘积严格小于 k 的连续子数组的数目。
算法:滑动窗口,从左边开始,慢慢将右指针 right 右移,满足条件则计入总数(以满足条件时的右指针为准),若 [ l , r ] 满足条件,则 [ l + 1 , r ] , [ l + 2 , r ] ... 一直到 [ r , r ] 都符合条件,则计算出公式 right - left + 1 。
代码:
class Solution {
public:
int numSubarrayProductLessThanK(vector<int>& nums, int k) {
if(k <= 1) return 0;
int left = 0,right = 0,prod = 1,ans = 0;
for(int right = 0;right < nums.size();right++){
prod *= nums[right];
while(prod >= k) prod /= nums[left++];//不满足条件,左指针右移
ans += right - left + 1;
}
return ans;
}
};
Leetcode 3. 无重复字符的最长子串
问题:给定一个字符串 s ,请你找出其中不含有重复字符的最长子串的长度。
算法:
hash 表做法,右指针 right 右移,出现重复元素则让左指针 left 右移,直到将重复元素消除,再更新窗口长度最大值 ans 。
代码:
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int left{},ans{};
unordered_set<char>window;// 维护从下标 left 到下标 right 的字符
for(int right = 0;right < s.size();right++){
char c = s[right];
// 如果窗口内已经包含 c,那么再加入一个 c 会导致窗口内有重复元素
// 所以要在加入 c 之前,先移出窗口内的 c
while(window.count(c)) window.erase(s[left++]); // 缩小窗口
window.insert(c);// 加入 c
ans = max(ans,right - left + 1);// 更新窗口长度最大值
}
return ans;
}
};