给定一个含有 n 个正整数的数组和一个正整数 target

找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [nums, nums, …, nums, nums] ,并返回其长度。如果不存在符合条件的子数组,返回 0

示例 1:

  1. Input: target = 7, nums = [2,3,1,2,4,3]
  2. Output: 2
  3. Explanation: The subarray [4,3] has the minimal length under the problem constraint.

示例 2:

  1. Input: target = 4, nums = [1,4,4]
  2. Output: 1

示例 3:

  1. Input: target = 11, nums = [1,1,1,1,1,1,1,1]
  2. Output: 0

提示:

  • 1 ≤ target ≤ 10;
  • 1 ≤ nums.length ≤ 10;
  • 1 ≤ nums[i] ≤ 10
  • 如果你已经实现 O(n) 时间复杂度的解法, 请尝试设计一个 O(n log(n)) 时间复杂度的解法。

思路

本题有两个思路,一个是暴力穷举,一个是滑动窗口(类似于双指针)。

对于滑动窗口,借用代码随想录的示意图:

长度最小的子数组-209 - 图1

我们新建两个指针,一个start指向起点,一个end指向终点。两个指针构成的闭区间就是我们所说的窗口

当区间的序列和 ≥ target时,我们就要把start指针向右移动。

如果最后startend重合,且指向的值不是target,则我们认为找不到长度最小的子数组,返回0

代码

Cpp:

  1. // 4ms, 10.2MB
  2. class Solution {
  3. public:
  4. int minSubArrayLen(int target, vector<int>& nums) {
  5. int start = 0, end = 0;
  6. unsigned cur_sum = 0;
  7. unsigned window_size = 0;
  8. unsigned result = 0xf << 15;
  9. for(end = 0; end < nums.size(); end++) {
  10. cur_sum += nums[end];
  11. while( cur_sum >= target ) {
  12. window_size = (end - start + 1);
  13. result = result < window_size ? result : window_size;
  14. cur_sum -= nums[start];
  15. start += 1;
  16. }
  17. }
  18. return (result == 0xf << 15 ? 0 : result);
  19. }
  20. };

Rust:

  1. // 0ms, 2.3MB
  2. impl Solution {
  3. pub fn min_sub_array_len(target: i32, nums: Vec<i32>) -> i32 {
  4. let mut start = 0;
  5. let mut end = 0;
  6. let mut cur_sum = 0;
  7. let mut windows_size = 0;
  8. let mut result = 0xf << 15;
  9. while end < nums.len() {
  10. cur_sum += nums[end];
  11. while cur_sum >= target {
  12. windows_size = (end - start + 1);
  13. result = if result < windows_size {
  14. result
  15. } else {
  16. windows_size
  17. };
  18. cur_sum -= nums[start];
  19. start += 1;
  20. }
  21. end += 1;
  22. }
  23. if result != 0xf << 15 {
  24. result as i32
  25. } else {
  26. 0
  27. }
  28. }
  29. }