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

相关推荐
橘子遇见BUG36 分钟前
算法日记 33 day 动态规划(打家劫舍,股票买卖)
算法·动态规划
格雷亚赛克斯39 分钟前
黑马——c语言零基础p139-p145
c语言·数据结构·算法
南宫生41 分钟前
力扣-位运算-3【算法学习day.43】
学习·算法·leetcode
Edward The Bunny42 分钟前
[算法] 前缀函数与KMP算法
算法
码农多耕地呗43 分钟前
区间选点:贪心——acwing
算法
醉酒柴柴1 小时前
【代码pycharm】动手学深度学习v2-08 线性回归 + 基础优化算法
深度学习·算法·pycharm
财富探秘者1 小时前
贵州茅台[600519]行情数据接口
大数据·c语言·python·算法·金融·restful
至善迎风1 小时前
施密特正交化与单位化的情形
线性代数·算法·决策树·机器学习
HABuo2 小时前
【数据结构与算法】合并链表、链表分割、链表回文结构
c语言·开发语言·数据结构·c++·学习·算法·链表
逸风尊者2 小时前
开发也能看懂的大模型:RNN
java·后端·算法