Leetcode209. 长度最小的子数组
有暴力解法和窗口滑动法,暴力解法是否值得掌握
暴力解法显然是一种简单而直观的解法,其时间复杂度为 O(N^2),空间复杂度为 O(1)。如果输入规模不大,暴力解法可能也可以接受。
但在面对规模较大,或对性能要求较高的场景下,暴力解法就会因其高时间复杂度而表现较差。此时就需要使用其他算法,如滑动窗口法,它的时间复杂度为 O(N),空间复杂度也为 O(1)。
因此,虽然暴力解法简单直观,但在开发实际项目中,我们通常需要考虑代码的效率和性能,所以掌握其他算法,如滑动窗口法等也是非常必要和有益的。但是,了解和掌握暴力解法也非常重要,因为在某些情况下它可能很有用,而且它也是其他算法的基础。
暴力解法
class Solution { public: int minSubArrayLen(int s, vector<int>& nums) { int result = INT32_MAX; // 最终的结果 int sum = 0; // 子序列的数值之和 int subLength = 0; // 子序列的长度 for (int i = 0; i < nums.size(); i++) { // 设置子序列起点为i sum = 0; for (int j = i; j < nums.size(); j++) { // 设置子序列终止位置为j sum += nums[j]; if (sum >= s) { // 一旦发现子序列和超过了s,更新result subLength = j - i + 1; // 取子序列的长度 result = result < subLength ? result : subLength; break; // 因为我们是找符合条件最短的子序列,所以一旦符合条件就break } } } // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列 return result == INT32_MAX ? 0 : result; } };
滑动窗口解法
滑动窗口是一种基于双指针的算法,它可以用于解决一些数组/字符串的子元素问题,例如:找到最长的子数组、最小的子串等等。
滑动窗口算法的思路就是维护两个指针,一个左指针和一个右指针,它们之间的区间就是滑动窗口。我们需要根据题目要求不断调整这两个指针的位置,来达到求解问题的目的。
在本题中,我们需要找到数组中满足其和 ≥ target 的长度最小的连续子数组,那么我们就可以使用滑动窗口算法来解决这个问题。
滑动窗口法的思路:
- 定义窗口的左右边界left,right初值为0
- 当窗口内的数字之和小于给定值时,调整右边界right,使窗口扩大
- 当窗口内的数字之和大于等于给定值时,记录窗口大小,并将左边界left向右移动一格,
具体步骤如下:
- 初始化左指针 i 和右指针 j,它们初始值都为 0。
- 初始化滑动窗口的数值之和 sum,初始值为 0。
- 当 sum < target 时,右指针向右移动一位,将 nums[j] 加入到 sum 中。
- 当 sum >= target 时,记录当前子数组的长度 (j - i + 1),并更新最小值。
- 然后移动左指针 i,将 nums[i] 从 sum 中减去,继续判断 sum 是否大于等于 target。
- 重复步骤 3-5,直到 j 超过数组范围。
这个算法的核心就是维护一个滑动窗口,不断调整左右指针的位置,来达到求解问题的目的。我们可以把这个过程想象成在一个数组上滑动一个大小可变的窗口,每次根据窗口内的值来判断左右指针的移动方式。
class Solution { public: int minSubArrayLen(int target, vector<int>& nums) { int result=INT32_MAX; int sum=0; int i=0; int subLength=0; //滑动窗口的长度 for(int j=0;j<nums.size();j++) { sum+=nums[j]; while(sum>=target) { subLength=(j-i+1); //取子序列的长度 result=result<subLength?result:subLength; //跟踪这个子数组的长度。 只有在找到更短的子数组时,才会更新此长度。它将最小长度分配给result变量。 sum-=nums[i++]; //5. 然后移动左指针 i,将 nums[i] 从 sum 中减去,继续判断 sum 是否大于等于 target。 //6. 重复步骤 3-5,直到 j 超过数组范围。 } } // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列 return result == INT32_MAX ? 0 : result; } };
相同的
class Solution { public: int minSubArrayLen(int target, vector<int>& nums) { int n=nums.size(); int left=0; int right=0; int sum=0; int result=INT_MAX; while(right<n) { sum+=nums[right]; while(sum>=target) { result=result<right-left+1?result:right-left+1; sum-=nums[left]; left++; } right++; } return result==INT_MAX?0:result; } };