赞
踩
创作不易,感谢三连
- class Solution {
- public:
- int minSubArrayLen(int target, vector<int>& nums)
- {
- int len=INT_MAX,n=nums.size(),sum=0;//len必须要给一个很大的数,否则
- for(int left=0,right=0;right<n;++right)
- {
- sum+=nums[right];//right进窗口
- while(sum>=target)//符合条件后进行更新,然后出窗口
- {
- len=min(len,right-left+1);//更新长度
- sum-=nums[left++];
- }
- }
- return len==INT_MAX?0:len;
- }
- };
- class Solution {
- public:
- int lengthOfLongestSubstring(string s)
- {
- int hash[128]={};//计数
- int len=0, n=s.size();
- for(int left=0,right=0;right<n;++right)
- {
- ++hash[s[right]];//进窗口
- while(hash[s[right]]>1) --hash[s[left++]];//出窗口
- len=max(len,right-left+1);//更新长度
- }
- return len;
- }
- };
- class Solution {
- public:
- int longestOnes(vector<int>& nums, int k)
- {
- int len=0;
- for(int left=0,right=0,zero=0;right<nums.size();++right)
- {
- if(nums[right]==0) ++zero;//进窗口
- while(zero>k) if(nums[left++]==0) --zero;//出窗口
- len=max(len,right-left+1);
- }
- return len;
- }
- };
- class Solution {
- public:
- int minOperations(vector<int>& nums, int x)
- {//将问题转化为求一个最长子数组 其大小正好==sum-x
- int ret=-1;
- int sum=accumulate(nums.begin(),nums.end(),0);//计算数组的总和
- int target=sum-x;//记录目标值
- if(target<0) return -1;//细节处理
- for(int left=0,right=0,temp=0,n=nums.size();right<n;++right)
- {
- temp+=nums[right];//进窗口
- while(temp>target) temp-=nums[left++];//出窗口
- if(temp==target) ret=max(ret,right-left+1);//更新结果
- }
- return ret==-1?-1:nums.size()-ret;
- }
- };
- class Solution {
- public:
- int totalFruit(vector<int>& fruits)
- {
- int hash[100001]={0};
- int ret=0,n=fruits.size();
- for(int left=0,right=0,kinds=0;right<n;++right)
- {
- if(hash[fruits[right]]++==0) ++kinds;//进窗口
- while(kinds>2) if(--hash[fruits[left++]]==0) --kinds;
- ret=max(ret,right-left+1);
- }
- return ret;
- }
- };
- class Solution {
- public:
- vector<int> findAnagrams(string s, string p)
- {
- vector<int> ret;
- int hash1[26]={0};//用来统计p的元素个数
- for(char ch:p) ++hash1[ch-'a'];
- int hash2[26]={0};//用来统计滑动窗口的元素个数
- int m=p.size();
- for(int left=0,right=0,count=0;right<s.size();++right)//count用来记录有效字符的个数
- {
- char in=s[right];
- if(++hash2[in-'a']<=hash1[in-'a']) ++count;//进窗口的同时统计有效字符个数
- if(right-left+1>m)//判断 出窗口
- {
- char out=s[left++];
- if(hash2[out-'a']--<=hash1[out-'a']) --count;
- }
- if(count==m) ret.push_back(left);
- }
- return ret;
- }
- };
- class Solution {
- public:
- string minWindow(string s, string t)
- {
- int hash1[128]={0};//统计t字符串个元素的出现次数
- int kinds=0;//用来统计种类
- for(char ch:t) if(hash1[ch]++==0) ++kinds;
- int hash2[128]={0};//统计s字符串中滑动窗口的元素出现次数
- int begin=-1,minlen=INT_MAX;//用来记录返回值情况
- for(int left=0,right=0,count=0;right<s.size();++right)
- {
- if(++hash2[s[right]]==hash1[s[right]]) ++count;//进窗口的同时统计窗口内元素种类
- while(count==kinds)//当种类都一样时,可以去更新结果
- {
- if(right-left+1<minlen)//因为还需要更新begin,所以不能直接用min
- {
- minlen=right-left+1;
- begin=left;
- }
- if(hash2[s[left]]--==hash1[s[left]]) --count;
- ++left;
- }
- }
- return begin==-1?"":s.substr(begin,minlen);
- }
- };
- class Solution {
- public:
- vector<int> findSubstring(string s, vector<string>& words)
- {
- int m=words.size();//单词个数
- int len=words[0].size();//每个单词的长度
- vector<int> ret;//用来返回
- unordered_map<string,int> hash1;//用来记录word的各个单词出现次数
- for(auto s:words) ++hash1[s];
- for(int i=0;i<len;++i)//要使用len次滑动窗口
- {
- unordered_map<string,int> hash2;//用来记录滑动窗口的各个单词出现次数
- for(int left=i,right=i,count=0;right+len-1<s.size();right+=len)//count用来有效子串
- {
- string in=s.substr(right,len);
- if(++hash2[in]<=hash1[in]) ++count;//进窗口顺便维护count
- if(right-left+1>len*m)//如果超过窗口的大小,就要出窗口
- {
- string out=s.substr(left,len);
- if(hash2[out]--<=hash1[out]) --count; //出窗口前要先维护count
- left+=len;//出窗口要更新left
- }
- if(count==m) ret.push_back(left);//如果count==m,说明有效子串达到要求
- }
- }
- return ret;
- }
- };
当题目涉及到子串或者是子数组,都可以考虑到使用滑动窗口来进行解决
但是有一个需要注意的地方就是如果涉及到窗口求和的话。要保证数都是正整数,否则就不满足单调性。如下图这一题
涉及到不同的种类需要统计数量的时候,常常会用到哈希表!! (5-7题)
后面有类似题目会持续更新!!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。