Leetcode 每日一题 209.长度最小的子数组

目录

问题描述

示例

算法分析

过题图片

[O(n) 时间复杂度解法](#O(n) 时间复杂度解法)

算法步骤

代码实现

[O(n log(n)) 时间复杂度解法](#O(n log(n)) 时间复杂度解法)

算法步骤

代码实现

题目链接

结论


问题描述

给定一个含有 n 个正整数的数组 nums 和一个正整数 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 解释:子数组 [4] 是满足条件的最短子数组。

  3. 输入:target = 11, nums = [1,1,1,1,1,1,1,1] 输出:0 解释:不存在和至少为 target 的子数组。

算法分析

这个问题可以通过滑动窗口的方法来解决,时间复杂度为 O(n)。滑动窗口是一种常见的解决子数组问题的方法,它通过维护一个窗口来遍历数组,窗口内的元素和满足一定的条件。

过题图片

O(n) 时间复杂度解法

算法步骤
  1. 初始化两个指针 startend,分别代表子数组的开始和结束位置,以及一个变量 sum 来存储当前窗口的和。
  2. 使用一个循环,通过移动 end 指针来扩大窗口,直到窗口内的和大于等于 target
  3. 一旦找到满足条件的窗口,尝试通过移动 start 指针来缩小窗口,同时更新最短长度 max
  4. 如果窗口的和小于 target,则继续移动 end 指针扩大窗口。
  5. 重复步骤 3 和 4,直到 end 指针遍历完整个数组。
  6. 如果 max 仍然是初始值,说明没有找到满足条件的子数组,返回 0;否则返回 max
代码实现
复制代码

java

复制代码
class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int start = 0;
        int end = 0;
        int sum = 0;
        int maxLen = Integer.MAX_VALUE;
        while (end < nums.length) {
            sum += nums[end];
            while (start <= end && sum >= target) {
                maxLen = Math.min(maxLen, end - start + 1);
                sum -= nums[start];
                start++;
            }
            end++;
        }
        return maxLen == Integer.MAX_VALUE ? 0 : maxLen;
    }
}

O(n log(n)) 时间复杂度解法

对于进阶要求,我们可以利用二分查找来优化滑动窗口的缩小过程,从而将时间复杂度降低到 O(n log(n))。这种方法的核心思想是在满足条件的窗口内,使用二分查找来确定可以向左扩展的最远距离。

算法步骤
  1. 同 O(n) 解法的初始化。
  2. 使用一个循环,通过移动 end 指针来扩大窗口,直到窗口内的和大于等于 target
  3. 使用二分查找在满足条件的窗口内找到最远的向左扩展距离。
  4. 更新最短长度 max
  5. 重复步骤 3 和 4,直到 end 指针遍历完整个数组。
  6. 返回 max 的值。
代码实现
复制代码

java

复制代码
class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int start = 0;
        int end = 0;
        int sum = 0;
        int maxLen = Integer.MAX_VALUE;
        while (end < nums.length) {
            sum += nums[end];
            while (start <= end && sum >= target) {
                int len = end - start + 1;
                if (len < maxLen) {
                    maxLen = len;
                }
                sum -= nums[start];
                start++;
            }
            end++;
        }
        return maxLen == Integer.MAX_VALUE ? 0 : maxLen;
    }
}

题目链接

209. 长度最小的子数组 - 力扣(LeetCode)

结论

通过滑动窗口的方法,我们可以有效地解决寻找和至少为 target 的最短子数组问题。O(n) 的解法适用于大多数情况,而 O(n log(n)) 的解法则在某些特定情况下可以提供更好的性能。

相关推荐
BUG收容所所长1 小时前
栈的奇妙世界:从冰棒到算法的华丽转身
前端·javascript·算法
XRZaaa1 小时前
常见排序算法详解与C语言实现
c语言·算法·排序算法
@我漫长的孤独流浪1 小时前
数据结构测试模拟题(4)
数据结构·c++·算法
智驱力人工智能1 小时前
智慧零售管理中的客流统计与属性分析
人工智能·算法·边缘计算·零售·智慧零售·聚众识别·人员计数
WindSearcher2 小时前
大模型微调相关知识
后端·算法
取酒鱼食--【余九】2 小时前
rl_sar实现sim2real的整体思路
人工智能·笔记·算法·rl_sar
Magnum Lehar4 小时前
vulkan游戏引擎test_manager实现
java·算法·游戏引擎
水蓝烟雨4 小时前
[面试精选] 0094. 二叉树的中序遍历
算法·面试精选
超闻逸事4 小时前
【题解】[UTPC2024] C.Card Deck
c++·算法
暴力求解5 小时前
C++类和对象(上)
开发语言·c++·算法