Given an array of n positive integers and a positive integer s, find the minimal length of a contiguous subarray of which the sum ≥ s. If there isn't one, return 0 instead.
Example:
Input:s = 7, nums = [2,3,1,2,4,3]Output: 2 Explanation: the subarray[4,3]has the minimal length under the problem constraint.
Follow up:
If you have figured out the O(n) solution, try coding another solution of which the time complexity is O(n log n).
解法一(暴力破解):
最简单直接的方法就是使用暴力破解法。设两个指针用于标识遍历数组过程中的起止位索引,遍历数组中每一种起止位的可能。然后保存更新最短的连续长度即可。
// O(n^2)
public static int minSubArrayLen(int s, int[] nums) {
int minLen = Integer.MAX_VALUE ;
for(int i=0; i < nums.length ; i++) {
int tempSum = 0;
for(int j=i; j<nums.length; j++) {
tempSum += nums[j] ;
if(tempSum >= s) {
minLen = Math.min(minLen, j - i + 1) ;
}
}
}
return minLen == Integer.MAX_VALUE ? 0 : minLen;
}
解法二(滑动窗口)
解法一时间复杂度显然是O(n^2),为了降低复杂度,可以使用滑动窗口。具体思想如下:假设找到了一组连续的子数组满足sum ≥ s,那么我们显然已经知道了这个子数组的起止位,也就是窗口的起止位。那么通过不断缩小窗口的大小,最终我们就可以得到最小的满足条件的窗口大小,也就是最短的子数组长度。
// O(n)
public static int minSubArrayLen(int s, int[] nums) {
int minLen = Integer.MAX_VALUE ;
int left = 0 ;
int sum = 0;
for(int i=0; i < nums.length ; i++) {
sum += nums[i] ;
while(sum >= s) {
minLen = Math.min(minLen, i - left + 1) ;
sum -= nums[left++] ;
}
}
return minLen == Integer.MAX_VALUE ? 0 : minLen;
}
Note:
这个算法里面虽然是双层循环,但是复杂度依然是O(n)的。原因在于数组中的每一位,至多只会被访问两次。一次是被指针left,另一次是被指针i。
本文探讨了在给定正整数数组中找到满足特定和条件的最短连续子数组的问题,提供了两种解决方案:暴力破解法(O(n^2))和滑动窗口法(O(n)),并详细解释了滑动窗口法如何在保持线性时间复杂度的同时,有效地找到满足条件的最小子数组。
1183

被折叠的 条评论
为什么被折叠?



