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)) 的解法则在某些特定情况下可以提供更好的性能。

相关推荐
蒋星熠9 分钟前
Flutter跨平台工程实践与原理透视:从渲染引擎到高质产物
开发语言·python·算法·flutter·设计模式·性能优化·硬件工程
小欣加油35 分钟前
leetcode 面试题01.02判定是否互为字符重排
数据结构·c++·算法·leetcode·职场和发展
3Cloudream39 分钟前
LeetCode 003. 无重复字符的最长子串 - 滑动窗口与哈希表详解
算法·leetcode·字符串·双指针·滑动窗口·哈希表·中等
王璐WL1 小时前
【c++】c++第一课:命名空间
数据结构·c++·算法
空白到白1 小时前
机器学习-聚类
人工智能·算法·机器学习·聚类
索迪迈科技2 小时前
java后端工程师进修ing(研一版 || day40)
java·开发语言·学习·算法
zzzsde2 小时前
【数据结构】队列
数据结构·算法
芒克芒克2 小时前
LeetCode 面试经典 150 题:删除有序数组中的重复项(双指针思想解法详解)
算法
青 .2 小时前
数据结构---二叉搜索树的实现
c语言·网络·数据结构·算法·链表
MChine慕青3 小时前
顺序表与单链表:核心原理与实战应用
linux·c语言·开发语言·数据结构·c++·算法·链表