LeetCode 209 题:长度最小的子数组

LeetCode 209 题:长度最小的子数组 (Minimum Size Subarray Sum)

LeetCode 第209题要求给定一个正整数数组 nums 和一个正整数 target,找出具有最小长度的连续子数组,使得子数组的和大于或等于 target。如果不存在这样的子数组,返回0。


题目描述

给定一个正整数数组 nums 和一个正整数 target,找出具有最小长度的连续子数组,使得子数组的和大于或等于 target。如果不存在这样的子数组,返回0。

示例 1

text 复制代码
输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 的和大于或等于 target 7,并且长度最小。

示例 2

text 复制代码
输入:target = 4, nums = [1,4,4]
输出:1

示例 3

text 复制代码
输入:target = 11, nums = [1,1,1,1,1,1,1,1]
输出:0

解题思路

  1. 暴力解法

    • 一个简单的暴力解法是使用双重循环,遍历所有可能的子数组并检查它们的和。这种方法的时间复杂度是 O ( n 2 ) O(n^2) O(n2),对于较大的输入,效率较低。
  2. 滑动窗口法

    • 通过滑动窗口来优化上述暴力解法。具体来说:
      • 使用两个指针,leftright,分别表示窗口的左边界和右边界。
      • 扩展右边界,逐步增大窗口的和。
      • 当窗口的和大于或等于 target 时,记录当前窗口的长度,并尝试缩小窗口的左边界以求最小长度。
      • 最终返回最小的符合条件的窗口长度。
  3. 复杂度分析

    • 时间复杂度 : O ( n ) O(n) O(n),因为左右指针分别从头到尾遍历数组。
    • 空间复杂度 : O ( 1 ) O(1) O(1),仅使用了常量空间来存储相关变量。

C语言代码实现

以下是使用滑动窗口法的代码实现:

c 复制代码
#include <stdio.h>
#include <stdlib.h>

int minSubArrayLen(int target, int* nums, int numsSize) {
    int left = 0, sum = 0, minLength = numsSize + 1;

    for (int right = 0; right < numsSize; right++) {
        sum += nums[right];

        // 当窗口和大于等于 target 时,尝试缩小窗口
        while (sum >= target) {
            minLength = (right - left + 1) < minLength ? (right - left + 1) : minLength;
            sum -= nums[left++];
        }
    }

    // 如果找到的最小长度大于数组长度,说明没有符合条件的子数组
    return minLength == numsSize + 1 ? 0 : minLength;
}

int main() {
    int nums[] = {2, 3, 1, 2, 4, 3};
    int target = 7;
    int result = minSubArrayLen(target, nums, 6);
    printf("最小长度为:%d\n", result);  // 输出:2

    return 0;
}

逐行解释代码

函数 minSubArrayLen
c 复制代码
int left = 0, sum = 0, minLength = numsSize + 1;
  • left:滑动窗口的左边界。
  • sum:当前窗口内所有元素的和。
  • minLength:记录符合条件的最小窗口长度,初始值为 numsSize + 1,表示未找到符合条件的子数组。

c 复制代码
for (int right = 0; right < numsSize; right++) {
    sum += nums[right];
  • right 是滑动窗口的右边界。
  • 我们通过扩展 right 边界,将 nums[right] 加到 sum 中,从而增大窗口的和。

c 复制代码
while (sum >= target) {
    minLength = (right - left + 1) < minLength ? (right - left + 1) : minLength;
    sum -= nums[left++];
}
  • 当窗口的和大于或等于 target 时,进入 while 循环,尝试缩小窗口以找到最小的符合条件的子数组。
  • 更新最小长度 minLength,计算当前窗口的大小 right - left + 1
  • nums[left]sum 中减去,并将 left 向右移动,缩小窗口。

c 复制代码
return minLength == numsSize + 1 ? 0 : minLength;
  • 如果 minLength 仍然等于 numsSize + 1,说明没有找到符合条件的子数组,返回 0。
  • 否则,返回找到的最小长度。

测试代码 main
c 复制代码
int nums[] = {2, 3, 1, 2, 4, 3};
int target = 7;
int result = minSubArrayLen(target, nums, 6);
printf("最小长度为:%d\n", result);  // 输出:2
  • 定义一个测试用例 nums = {2, 3, 1, 2, 4, 3}target = 7
  • 调用 minSubArrayLen 函数计算结果并打印。

测试结果

运行代码后输出:

text 复制代码
最小长度为:2

复杂度分析

  1. 时间复杂度 : O ( n ) O(n) O(n)

    • 滑动窗口法的时间复杂度是 O ( n ) O(n) O(n),因为每个元素最多被访问两次(一次通过 right 扩展窗口,一次通过 left 收缩窗口)。
  2. 空间复杂度 : O ( 1 ) O(1) O(1)

    • 我们只用了常量空间来存储一些临时变量(leftsumminLength),因此空间复杂度为 O ( 1 ) O(1) O(1)。
相关推荐
qy发大财几秒前
跳跃游戏(力扣55)
算法·leetcode
BingLin-Liu4 分钟前
蓝桥杯备考:搜索算法之排列问题
算法·职场和发展·蓝桥杯
计算机小白一个7 分钟前
蓝桥杯 Java B 组之岛屿数量、二叉树路径和(区分DFS与回溯)
java·数据结构·算法·蓝桥杯
孤雪心殇8 分钟前
简单易懂,解析Go语言中的Map
开发语言·数据结构·后端·golang·go
curemoon1 小时前
理解都远正态分布中指数项的精度矩阵(协方差逆矩阵)
人工智能·算法·矩阵
柃歌1 小时前
【UCB CS 61B SP24】Lecture 7 - Lists 4: Arrays and Lists学习笔记
java·数据结构·笔记·学习·算法
柃歌1 小时前
【UCB CS 61B SP24】Lecture 4 - Lists 2: SLLists学习笔记
java·数据结构·笔记·学习·算法
干炒 牛河1 小时前
数据结构:双链表list
数据结构·list
SKYDROID云卓小助手2 小时前
无人设备遥控器之如何分享数传篇
网络·人工智能·算法·计算机视觉·电脑
Lqingyyyy3 小时前
P2865 [USACO06NOV] Roadblocks G 与最短路的路径可重复的严格次短路
开发语言·c++·算法