209. 长度最小的子数组
题目描述:
给定一个含有 n
个正整数的数组和一个正整数 target
。
找出该数组中满足其总和大于等于 target
的长度最小的 连续子数组[numsl, numsl+1, ..., numsr-1, numsr]
,并返回其长度。如果不存在符合条件的子数组,返回 0
。
解题思路:
我们通过题目得知,本题是一个正数数列,题目要求求出最小连续子数组,假设子数组之和为sum
假设从左到右,我们每加一个数,sum都是增大,每减一个数,sum都是减小,这就是具有单调性
所以我们可以用两个指针left和right(一开始都是在0的位置)来当做窗口的左右边界,当right向右移动的时候,sum为这个窗口之和,当right向右,sum递增,当left向右,sum递减(当双指针运动方向相同的时候称为同向双指针),当sum>=target,出窗口(left++),否则进窗口(right++),还需要更新length(最小长度)。
时间复杂度:虽然代码是两层循环,但是我们的 left 指针和 right 指针都是不回退的,两者
最多都往后移动 n 次。因此时间复杂度是 O(N) 。
解题代码:
class Solution { public: int minSubArrayLen(int target, vector<int>& nums) { int length = INT_MAX; int n = nums.size(); int left = 0; int right = 0; int sum = 0; while(right<n) { sum+=nums[right]; while(sum>=target) { length=min(length,right-left+1); sum-=nums[left++]; } right++; } return length==INT_MAX?0:length; } };
3. 无重复字符的最长子串
题目描述:
给定一个字符串 s
,请你找出其中不含有重复字符的 最长子串 的长度。
解题思路:
依旧是利用滑动窗口
解题代码:
class Solution { public: bool str(string&s,int left,int right,char ch) { for(int i=left;i<=right;i++) { if(ch==s[i]) return false; } return true; } int lengthOfLongestSubstring(string s) { int length=0; int left=0,right=0; int n=s.size(); while(right<n) { while(!str(s,left,right-1,s[right])) left++; length=max(length,right-left+1); right++; } return length; } };