双索引技术(Two Pointer)
滑动窗口:这两个索引表示的是一个窗口,让这个窗口不停的在数组中滑动,来找到问题的解。
-什么叫子数组:可以不连续。但是本题强调了是要连续的。、
解法一:滑动窗口
时间复杂度:O(n),空间复杂度O(1) 因为没有另外开辟空间。
class Solution { public: int minSubArrayLen(int s, vector<int>& nums) { //初始化,希望区间不包含任何元素 int l = 0, r = -1; //nums[l...r]为我们的滑动窗口 int sum = 0; //和 int res = nums.size()+1; //连续子数组初始化为数组的长度+1 while(l<nums.size()){ if(r+1<nums.size() && sum<s){ r++; sum += nums[r]; //应注意r的取值不能越界 } else{ sum -= nums[l]; l++; } if(sum >= s) res = min(res, r-l+1); } if(res == nums.size()+1) return 0; return res; } };
思路:和209类似采用滑动窗口的思路。在[l...r]区间中表示不重复的字符集,为了扩大当前的字符集,加载一位新的元素时要判断新元素是否在[l...r]中,若不在扩大r+1,若在就将左边界l减至重复元素之后。在此期间不断更新维护字符区间的长度。
如何判断新的元素是否在字符集区间呢?遍历查找?find?这里有个小技巧,查表
预定义一个256大小的数组来维护字符集区间内元素出现的频率freq[256]初始为0,当加入1个元素对应的元素下标+1,当从字符集中删除一个元素对应删除元素下标需要-1,最终通过查表来看该元素是否在字符集空间。 这个想法很巧妙啊 :)
class Solution { public: int lengthOfLongestSubstring(string s) { int freq[256] = {0}; //记录数组中的字符出现的频率 int l=0, r = -1; //滑动窗口为s[l...r] int res = 0; //满足条件的字串的最长长度 while(l<s.size()){ if(r+1<s.size() && freq[s[r+1]]==0){ //r+1为下标的字符出现的频率为0时,可以向右扩张 r++; freq[s[r]]++; } else{ //重复出现时,左侧窗口向右移,即缩小 freq[s[l]]--; l++; } res = max(res, r-l+1); } return res; } };
原文地址:https://www.cnblogs.com/Bella2017/p/10159234.html
时间: 2024-11-09 00:46:39