题目描述:
给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的连续子数组,并返回其长度。如果不存在符合条件的连续子数组,返回 0。
今日学习:
1.二分法复习
2.滑动窗口复习
3.前缀和复习
题解:
1.暴力法:O(n²),O(1)
2.滑动窗口:O(n),O(1)
3.前缀和+二分法:O(nlogn),O(n)
//暴力法居然没超时
var minSubArrayLen = function(s, nums) {
if(nums.length == 0) return 0
let res = Number.MAX_VALUE
let left = right = 0
while(left < nums.length) {
let sum = 0
let count = 0
right = left
for(; right < nums.length; right++) {
sum += nums[right]
if(sum >= s) {
count = right - left + 1
res = Math.min(res, count)
break
}
}
left++
}
return res == Number.MAX_VALUE ? 0 : res
};
//双指针移动滑动窗口,其实我写完暴力法就想到了可以存下中间的sum省去一部分计算,但是开始没想明白怎么做
var minSubArrayLen = function(s, nums) {
if(nums.length == 0) return 0
let res = Number.MAX_VALUE
let left = right = sum = 0
while(right < nums.length) {
sum += nums[right]
while(sum >= s) {
res = Math.min(res, right - left + 1)
sum -= nums[left]
left++
}
right++
}
return res == Number.MAX_VALUE ? 0 : res
}
//前缀和+二分查找
var minSubArrayLen = function(s, nums) {
let n = nums.length
if(n == 0) return 0
let res = Number.MAX_VALUE
let sums = new Array(n + 1).fill(0)
for(let i = 1; i < n + 1; i++) {
sums[i] = sums[i - 1] + nums[i - 1]
}
for(let i = 1; i < n + 1; i++) {
let target = s + sums[i - 1]
let flag = binarySearch(target, i, sums)
if(flag != -1) {
res = Math.min(res, flag - i + 1)
}
}
return res == Number.MAX_VALUE ? 0 : res
}
var binarySearch = function(target, start, sums) {
let end = sums.length - 1
while(start < end) {
let mid = (start + end) >> 1
if(sums[mid] < target) {
start = mid + 1
}else {
end = mid
}
}
return sums[start] >= target ? start : -1
}