392.判断子序列
-
难度级别:中等
-
题目类型:滑动窗口
-
题目描述:209. 长度最小的子数组 - 力扣(LeetCode)
-
-
给定一个含有
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))
时间复杂度的解法。
解题思路:
-
-
-
暴力解法(超出时间限制)
-
思路:初始化子数组的最小长度为无穷大,枚举数组 nums 中的每个下标作为子数组的开始下标,对于每个开始下标 i ,需要找到大于或等于 i 的最小下标 j ,使得从 nums[i] 到 nums[j] 的元素和大于或等于s,并更新子数组的最小长度,此时,子数组的长度为 j - i + 1。
-
复杂度 时间复杂度 O(n2) 空间复杂度 O(1) -
源代码:
//暴力解法 超出时间限制 class Solution { public int minSubArrayLen(int target, int[] nums) { int result = 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) { result = Math.min(result, j - i + 1); break; } } } return result == Integer.MAX_VALUE ? 0 : result; } }
-
-
滑动指针
-
思路:
- 定义两个指针 start 和 end ,其分别表示子数组(滑动窗口)的开始位置和结束位置,维护变量 sum 存储子数组中的元素和(nums[start] + nums[end])
- 初始状态时,start 和 end 都指向下标 0,sum 的值为 0;
- 每一轮迭代,将 nums[end] 加到 sum ,如果sum >= target ,则更新子数组的最小长度(end - start + 1),然后将 nums[start] 从 sum 中减去,并将 start 右移,直到 sum < target ,在此过程中同样更新子数组的最小长度,在每一轮迭代的最后,将end 右移。
-
复杂度 时间复杂度 O(n) 空间复杂度 O(1) -
源代码:
//滑动指针 class Solution { public int minSubArrayLen(int target, int[] nums) { int result = Integer.MAX_VALUE; int start = 0, end = 0, sum = 0; while(end < nums.length) { sum += nums[end]; while(sum >= target) { result = Math.min(result, end - start + 1); sum -= nums[start]; ++ start; } ++ end; } return result == Integer.MAX_VALUE ? 0 : result; } }
-