leetcode 面试经典 150 题:长度最小的子数组

链接长度最小的子数组
题序号209
题型数组
解题方法滑动窗口
难度中等

题目

给定一个含有 n 个正整数的数组和一个正整数 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

  • 示例 3:
    输入:target = 11, nums = [1,1,1,1,1,1,1,1]
    输出:0

  • 提示:
    1 <= target <= 109
    1 <= nums.length <= 105
    1 <= nums[i] <= 104

  • 进阶:
    如果你已经实现 O(n) 时间复杂度的解法, 请尝试设计一个 O(n log(n)) 时间复杂度的解法。

题解

滑动窗口法

  1. 子数组:是数组中连续的、非空元素序列。

  2. 核心要点

    • 滑动窗口:使用滑动窗口(双指针)的方法来解决这个问题。定义两个指针 left 和 right,分别表示子数组的开始和结束位置。
    • 窗口和:维护一个变量 sum,表示当前窗口内元素的和。
    • 窗口移动:当 sum < s 时,移动 right 指针向右扩展窗口,并将 nums[right] 加入 sum。当 sum ≥ s 时,记录当前窗口的长度,并尝试移动 left 指针向右缩小窗口,同时从 sum 中减去 nums[left]。
    • 最小长度:在每次满足 sum ≥ s 时,更新最小长度的记录。
  3. 时间复杂度:O(n),因为每个元素最多被访问两次(一次被 right 指针访问,一次被 left 指针访问)。

  4. 空间复杂度:O(1),因为只使用了常数级别的额外空间

  5. c++ 实现算法

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int n = nums.size();
        int left = 0; // 滑动窗口左边界
        int sum = 0;  // 当前窗口的总和
        int minLength = INT_MAX; // 最小子数组长度,初始化为无穷大

        for (int right = 0; right < n; ++right) {
            sum += nums[right]; // 将当前元素加入窗口

            // 当窗口内的和满足 >= target 时,尝试缩小窗口
            while (sum >= target) {
                minLength = min(minLength, right - left + 1); // 更新最小长度
                sum -= nums[left]; // 从窗口中移除左边界的值
                ++left; // 左边界右移
            }
        }

        // 如果没有找到符合条件的子数组,返回 0
        return minLength == INT_MAX ? 0 : minLength;
    }
};
  1. 演示:以示例1为例
    在这里插入图片描述

  2. c++完整demo

#include <iostream>
#include <vector>
#include <climits> // for INT_MAX
using namespace std;

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int n = nums.size();
        int left = 0; // 滑动窗口左边界
        int sum = 0;  // 当前窗口的总和
        int minLength = INT_MAX; // 最小子数组长度,初始化为无穷大

        for (int right = 0; right < n; ++right) {
            sum += nums[right]; // 将当前元素加入窗口

            // 当窗口内的和满足 >= target 时,尝试缩小窗口
            while (sum >= target) {
                minLength = min(minLength, right - left + 1); // 更新最小长度
                sum -= nums[left]; // 从窗口中移除左边界的值
                ++left; // 左边界右移
            }
        }

        // 如果没有找到符合条件的子数组,返回 0
        return minLength == INT_MAX ? 0 : minLength;
    }
};

int main() {
    Solution solution;
    vector<int> nums = {2, 3, 1, 2, 4, 3};
    int target = 7;

    int result = solution.minSubArrayLen(target, nums);
    cout << "result: " << result << endl; // 输出 2
    return 0;
}

滑动窗口法和双指针法

滑动窗口和双指针是解决数组和字符串问题中常用的两种技术,它们在某些情况下可以相互转换,但它们的概念和应用场景有所不同。下面我将分别解释这两种技术,并说明它们的主要区别。

滑动窗口

滑动窗口是一种处理 固定长度或动态长度窗口内元素的技术,常用于解决需要在连续子数组或子字符串中寻找特定属性的问题。 滑动窗口的核心思想是维护一个窗口,随着遍历的进行,窗口内包含的元素会不断变化。

特点:

  • 窗口可以是固定长度,也可以是动态变化的。
  • 窗口内的操作通常是累加、累乘或者比较。
  • 滑动窗口可以用于寻找子数组或子字符串的最大/最小值、和、乘积等。

应用场景:

  • 寻找子数组的和或乘积满足特定条件的最小/最大长度。
  • 判断子数组是否包含特定数量的不同元素。
  • 实现一些需要连续性条件的数据流统计。

双指针

双指针技术通常涉及两个指针(或索引),它们在数组或字符串中以不同的速度移动,用于解决需要比较元素之间相对位置的问题。

特点:

  • 两个指针可以同时移动,也可以一个快一个慢。
  • 双指针常用于比较、排序、去重、寻找特定模式等问题。
  • 双指针可以用于解决有序数组中的特定问题,如寻找两个数的和、差等。

应用场景:

  • 寻找两个指针之间的特定关系,如两数之和为特定值。
  • 判断一个数组是否为回文(快慢指针相向而行)。
  • 实现归并排序、快速排序中的合并和分区步骤。

区别

  • 窗口大小:滑动窗口通常有一个明确的窗口大小,而双指针不一定有固定的大小概念。
  • 移动方式:滑动窗口通常是单向移动(如向右扩展),而双指针可以相向而行或同向而行。
  • 问题类型:滑动窗口更适合解决需要连续性的问题,而双指针更适合解决需要比较元素相对位置的问题。
  • 灵活性:双指针在某些情况下比滑动窗口更灵活,因为它们可以独立控制每个指针的移动。

在实际应用中,滑动窗口和双指针可以根据问题的具体需求相互转换。例如,滑动窗口问题可以通过设置两个指针来模拟,而某些双指针问题也可以通过扩展窗口来解决。理解这两种技术的核心思想和适用场景,可以帮助你更有效地解决算法问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/938853.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vue 设置 VUE_APP_TITLE 打包部署后不生效

VUE_APP_TITLE 名门望族云科技有限公司网站 这里的 名门望族云科技有限公司网站 两边不能加 (单引号) 部署后,浏览器刷新网站根目录

经济研究复刻:企业ESG表现与创新(2009-2023年)

参照方先明&#xff08;2023&#xff09;的做法&#xff0c;对来自经济研究《企业ESG表现与创新—来自A股上市公司的证据》一文中的基准回归部分进行复刻。论文基于利益相关者理论分析了ESG表现对企业创新可能的影响及机制&#xff0c;利用2009-2023年A股上市公司的专利数据&am…

ECharts 手势框选方案:实现鼠标自由刷选区域,定向放大图表(文末附源码)

一. 背景 在 ECharts 中&#xff0c;图表开发属于最基础的组件开发&#xff0c;适合统计展示各种各样的数据&#xff0c;使用图形化的效果将海量数据直观的展示给用户&#xff0c;以便于让用户能够快速获取到数据展示及走向。但随着用户需求的不断迭代&#xff0c;我们最近的一…

卡尔曼滤波器的实用方法及其实现方法

前言 卡尔曼滤波器对于不熟悉的人来说就是一种算法,它使用随时间观察的一系列观量值,,加速度计和陀螺仪在测量值是就会包含测量误差的噪声.卡尔曼滤波器将尝试根据当前和以前的状态来估计系统的状态,这往往比测量更加的精准.问题在于机器人来回的移动,加速度计在用于测量重力加…

QScreen在Qt5.15与Qt6.8版本下的区别

简述 QScreen主要用于提供与屏幕相关的信息。它可以获取有关显示设备的分辨率、尺寸、DPI&#xff08;每英寸点数&#xff09;等信息。本文主要是介绍Qt5.15与Qt6环境下&#xff0c;QScreen的差异&#xff0c;以及如何判断高DPI设备。 属性说明 logicalDotsPerInch&#xff1…

0004.基于springboot+elementui的在线考试系统

适合初学同学练手项目&#xff0c;部署简单&#xff0c;代码简洁清晰&#xff1b; 愿世界和平再无bug 一、系统架构 前端&#xff1a;vue| elementui 后端&#xff1a;springboot | mybatis-plus 环境&#xff1a;jdk1.8 | mysql | maven 二、登录角色 1.管理员 2.老师 …

【Laravel】端口问题导致菜单打不开

以下是修改 Laravel 应用程序的端口配置&#xff0c; 修改环境变量 APP_URL 来实现 app/Providers/AppServiceProvider.php <?phpnamespace App\Providers;use Illuminate\Events\Dispatcher; use Illuminate\Support\ServiceProvider; use Illuminate\Support\Facades\URL…

【数据分析】数据结构数据内容概述

文章目录 表格结构数据特征数据类别结构化数据表格结构数据层级表格结构的数据类型单元格的格式属性 表格结构数据获取方法从企业后台数据库系统获取后台数据库系统获取数据流程前端操作平台获取从企业外部渠道获取数据 表格结构数据使用方法单元格值的引用方法单元格区域值的引…

makefile文件

简介&#xff1a; 自动化编译&#xff1a;只需要一个make命令&#xff0c;整个工程自动编译 提高编译效率&#xff1a;再次编译时&#xff0c;只编译修改的文件&#xff08;查看时间戳&#xff0c;根据修改文件的时间判断文件是否被修改&#xff09; 基本语法&#xff1a; …

STM32-笔记3-驱动蜂鸣器

1、复制03项目&#xff0c;重命名为04项目 打开04项目的Drivers/BSP/led文件夹&#xff0c;把led文件夹更改为beep文件夹&#xff0c;改文件夹内部的.c和.h文件更改为beep.c和beep.h文件&#xff0c;如下图所示。 2、打开工程文件 出现弹窗&#xff0c;显示找不到xx文件&#…

阿尔茨海默症数据集,使用yolo,voc,coco格式对2013张原始图片进行标注,可识别轻微,中等和正常的症状

阿尔茨海默症数据集,使用yolo&#xff0c;voc&#xff0c;coco格式对2013张原始图片进行标注&#xff0c;可识别轻微&#xff0c;中等&#xff0c;严重和正常的症状 数据集分割 训练组100&#xff05; 2013图片 有效集&#xff05; 0图片 测试集&#xf…

uniapp v-tabs修改了几项功能,根据自己需求自己改

根据自己的需求都可以改 这里写自定义目录标题 1.数组中的名字过长&#xff0c;导致滑动异常2.change 事件拿不到当前点击的数据&#xff0c;通过index在原数组中查找得到所需要的id 各种字段麻烦3.添加指定下标下新加红点显示样式 1.数组中的名字过长&#xff0c;导致滑动异常…

k8s kubernetes

文章目录 CGroupk8s运行时k8s组件k8s组件安装kubeadm命令kubectl命令k8s官网代码 CGroup 在 Linux 上&#xff0c;控制组&#xff08;CGroup&#xff09;用于限制分配给进程的资源。kubelet 和底层容器运行时都需要对接控制组来强制执行 为 Pod 和容器管理资源 并为诸如 CPU、…

学习笔记072——Java中的【JUC 并发编程】

文章目录 JUC 并发编程1、什么是高并发2、Java 实现多线程的第三种方式3、sleep 和 wait 方法的区别4、synchronized 锁定的是谁&#xff1f;5、ConcurrentModificationException6、JUC 工具类7、读写锁8、线程池 JUC 并发编程 JUC 是指 Java 并发编程工具包 java.util.concu…

【报错解决】vsvars32.bat 不是内部或外部命令,也不是可运行的程序或批处理文件

报错信息&#xff1a; 背景问题&#xff1a;Boost提示 “cl” 不是内部或外部命令&#xff0c;也不是可运行的程序或批处理文件时&#xff0c;   按照这篇博客的方法【传送】添加了环境变量后&#xff0c;仍然报错&#xff1a; 报错原因&#xff1a; vsvars32.bat 的路径不正…

简单配置,全面保护:HZERO审计服务让安全触手可及

HZERO技术平台&#xff0c;凭借多年企业资源管理实施经验&#xff0c;深入理解企业痛点&#xff0c;为您提供了一套高效易用的审计解决方案。这套方案旨在帮助您轻松应对企业开发中的审计挑战&#xff0c;确保业务流程的合规性和透明度。 接下来&#xff0c;我将为大家详细介绍…

使用nvm对node进行多版本管理

1.nvm下载及安装 下载链接 下载完成后&#xff0c;对文件进行解压安装&#xff0c;按照提示一步步安装&#xff0c;如果电脑上之前有安装过node&#xff0c;需要先卸载&#xff0c;再进行安装。 按照提示完成安装。 2.设置环境变量 可以现在C:\Users\name\AppData\Roamin…

【JavaEE初阶】JavaScript相应的WebAPI

目录 &#x1f332;WebAPI 背景知识 &#x1f6a9;什么是 WebAPI &#x1f6a9;什么是 API &#x1f38d;DOM 基本概念 &#x1f6a9;什么是 DOM &#x1f6a9;DOM 树 &#x1f340;获取元素 &#x1f6a9;querySelector &#x1f6a9;querySelectorAll &#x1f384…

基于MNE的EEGNet 神经网络的脑电信号分类实战(附完整源码)

利用MNE中的EEG数据&#xff0c;进行EEGNet神经网络的脑电信号分类实现&#xff1a; 代码&#xff1a; 代码主要包括一下几个步骤&#xff1a; 1&#xff09;从MNE中加载脑电信号&#xff0c;并进行相应的预处理操作&#xff0c;得到训练集、验证集以及测试集&#xff0c;每个…

SCHEMA find old payroll result

这几天原来HK客户要我帮忙看一个问题&#xff0c;在看HK雇佣条例时&#xff0c;发现又假期是取前12个月的工资&#xff0c;后来查看标准函数发现两个有用的operation&#xff0c;PLOOP与IMPRE 下图是2012年6月工资核算&#xff0c;现在循环着前面4个月。 输入 输出 2012年5月…