1.题目描述
给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
示例 1:
输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。
示例 2:
输入:target = 4, nums = [1,4,4]
输出:1
示例 3:
输入:target = 11, nums = [1,1,1,1,1,1,1,1]
输出:0
提示:
- 1 <= target <= 109
- 1 <= nums.length <= 105
- 1 <= nums[i] <= 105
进阶:
如果你已经实现 O(n) 时间复杂度的解法, 请尝试设计一个 O(n log(n)) 时间复杂度的解法。
来源:力扣(LeetCode)
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
2.题解
2.1 暴力
2.1.1 思路
暴力法有手就行(不是)。
双重循环从i开始一直遍历到末尾,如果碰到符合条件的就直接更新答案。
2.1.2 Java代码
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int ans = Integer.MAX_VALUE;
for(int i=0;i<nums.length;i++){
int sum = 0;
for(int j = i;j<nums.length;j++){
sum += nums[j];
if(sum>=target&&(j-i+1)<ans){
ans = j-i+1;
}
}
}
if(ans != Integer.MAX_VALUE){
return ans;
}
else{
return 0;
}
}
}
2.2 二分
2.2.1 思路
二分法将时间复杂度变成了O(nlogn)。
因为数组中所有的数都为正数,所以将数累加成的sum[]数组是递增的,因此可以使用二分法。
其实是从sum[0]开始找的,在sum中找到符合sum[i-1]+target,也就是从sum[s]-sum[i-1]>target。
而其中的- bound -1是因为在Java的Arrays.binarySearch()中如果找不到该值就会返回(-(插入点)-1)。而所得的值反一下就是插入点了。
最后不要忘记判断一下bound是不是超过num。
2.2.2 Java代码
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int num = nums.length;
if(num == 0){
return 0;
}
int []sum = new int[num+1];
for(int i=0;i<num;i++){
sum[i+1] = sum[i]+nums[i];
}
int ans = Integer.MAX_VALUE;
for(int i=1;i<=num;i++){
int s = target + sum[i-1];
int bound = Arrays.binarySearch(sum,s);
if(bound<0){
bound = -(bound+1);
}
if (bound <= num) {
ans = Math.min(ans, bound - (i - 1));
}
}
if(ans<Integer.MAX_VALUE){
return ans;
}
return 0;
}
}