LeedCode 209
题目:给定一个含有 n
个正整数的数组和一个正整数 target
。
找出该数组中满足其和 ≥ target
的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr]
,并返回其长度。如果不存在符合条件的子数组,返回 0
。
--》我的想法:
当时我对滑动窗口的“滑动”二字理解并不深刻,仅仅以为“滑动”不过是两个指针控制一个窗口的初末位置。当时我写的伪代码:
if(sum < target) j++;//窗口右边++
else if(sum >= target) i++;//窗口左边++
当时想的就是想办法循环上面的两行代码,并把sum想办法更新就完事了(sum是窗口中数字的和,即)
--》滑动窗口:
怎么理解“滑动”呢?写完本题之后,sum其实不需要更新多次,比如i++之后,按我之前的想法还需要重新算一遍sum,但是完全可以用sum -= nums[i]来代替,这样就不需要重新计算sum。归根结底,这样遍历完整个数组,对于sum:相当于只完完全全的计算了一遍sum,而对于元素:每个元素只有出窗口和入窗口的时候用到了,所以时间复杂度是O(2n)=O(n)。【后续可能会有新的理解】
代码:
for(int j=0;j<nums.size();j++)
{
sum += nums[j];//j是右边
while(sum >= target)
{
result = min(result,j-i+1);//用min的时候要加上#include <algorithm>
sum -= nums[i++];
}
return result == INT32_MAX ? 0:result;
加个完整代码:
#include<bits/stdc++.h>
using namespace std;
int minSubArrayLen(int target, vector<int>& nums) {
int sum =0;
int result = INT32_MAX;
int i=0;
for(int j=0;j<nums.size();j++)
{
sum += nums[j];//j是右边
while(sum >= target)
{
result = min(result,j-i+1);//用min的时候要加上#include <algorithm>
sum -= nums[i++];
}
}
return result == INT32_MAX ? 0:result;
}
int main()
{
vector <int> nums = {2,3,1,2,4,3};
cout<<minSubArrayLen(7,nums);
return 0;
}
- LeedCode 3
题目:给定一个字符串 s
,请你找出其中不含有重复字符的 最长子串 的长度。
滑动窗口只是一个思想,想要会写代码,还得具备牢固的C++知识,为了写这一题,又去看了map,unordered_map,set,unordered_set。学完基础知识之后,发现利用封装好的函数去解这题也不算难。
下面附上代码:
#include <bits/stdc++.h>
using namespace std;
int lengthOfLongestSubstring(string s) {
if(s.size() == 0) return 0;
set<char> lookup;
int maxStr = 0;
int left = 0;
for(int i = 0; i < s.size(); i++){
while (lookup.find(s[i]) != lookup.end()){
lookup.erase(s[left]);
left ++;
}
maxStr = max(maxStr,i-left+1);
lookup.insert(s[i]);
}
return maxStr;
}
int main()
{
string s = "abcabcbb";
cout<<lengthOfLongestSubstring(s);
return 0;
}
- LeedCode 904
说白了就是①找遍历所有窗口,②剔除掉不合题意的窗口,③然后从剩下的窗口中,找到长度最大的。
本题中的不合题意是指:窗口内元素种类数目大于2;所以遍历所有窗口的时候要剔除掉这种窗口
方法:哈希表+滑动窗口
int totalFruit(vector<int>& fruits) {
map <int,int> mymap;
int left = 0;//窗口左边
int win_size = 0;//窗口长为0
//1、遍历所有窗口
for(int i = 0;i<fruits.size();i++)
{
mymap[fruits[i]]++;/*这一行将fruits[i]这个元素加入到mymap中,只要i++之后就一定会执行这句话,所以这句话放到了while循环之外。*/
//2、(相当于)剔除种类数大于2的窗口
while(mymap.size()>2)
{
mymap[fruits[left]]--;
if(mymap[fruits[left]]==0) mymap.erase(fruits[left]);
left++;
}
//3、找到窗长最大的
win_size = max(win_size,i-left+1);
}
return win_size;
}