当前位置: 首页 > article >正文

每日一题:⻓度最⼩的⼦数组

文章目录

  • 一、题目
  • 二、解析
    • 1、暴力算法
      • (1)纯暴力
      • (2)前缀和 + 循环
    • 2、滑动窗口

一、题目

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] <= 105

二、解析

1、暴力算法

(1)纯暴力

纯暴力的话,就是用两个循环变量,代表一个区间的左端点和右端点,然后再用一个指针去循环这个区间得到这个区间的区间和。最终得到最小的长度区间。时间复杂度:O(n³)

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        // 记录满足条件的区间最小长度
        int len = INT_MAX;
        // 用两个循环得到这个nums的所有子区间
        for (int l = 0; l < nums.size(); l++)
        {
            for (int r = l; r < nums.size(); r++)
            {
                int sum = 0;
                // 获得区间和
                for (int i = l; i <= r; i++)
                    sum += nums[i];
                // 寻找满足条件的区间
                if (sum >= target) len = min(len, r - l + 1);
            }
        }
        // 返回答案
        return len == INT_MAX ? 0 : len;
    }
};

(2)前缀和 + 循环

我们通过优化掉两个循环中的获取区间和的循环,降低了一层循环。时间复杂度:O(n²)

我们在双重循环之前先求出该数组的前缀和,这样的话获得区间和的操作就是O(1)

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        // 前缀和
        vector<int> s(nums.size(), 0);
        s[0] = nums[0];
        for (int i = 1; i < nums.size(); i++)
            s[i] = s[i - 1] + nums[i];
        // 记录满足条件的区间最小长度
        int len = INT_MAX;
        // 用两个循环得到这个nums的所有子区间
        for (int l = 0; l < nums.size(); l++)
        {
            for (int r = l; r < nums.size(); r++)
            {
                // 获得区间和
                // 如果s是从下标0开始存储的话:区间和sum = s[r] - s[l] + nums[l]
                // 如果s是从下标1开始存储的话:区间和sum = s[r] - s[l - 1]
                // 上述的结论可以自行体会
                int sum = s[r] - s[l] + nums[l];
                
                // 寻找满足条件的区间
                if (sum >= target) len = min(len, r - l + 1);
            }
        }
        // 返回答案
        return len == INT_MAX ? 0 : len;
    }
};

2、滑动窗口

根据上面的步骤,我们真的需要每次都需要j从i的位置开始遍历吗?

其实是不需要的,因为当区间和大于等于target的时候,我们将左边界向右移动,这时该区间和一定小于之前,我们只需要继续往右移动。

时间复杂度:O(n)

image-20240926213242320

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        // 定义区间边界
        int l = 0, r = 0, n = nums.size();
        int sum = 0;
        int len = INT_MAX;
        // 持续更新右边界
        while (r < n) {
            // 进入窗口
            sum += nums[r++];
            // 判断,是否需要滑出窗口
            while (sum >= target) {
                len = min(len, r - l);
                sum -= nums[l++];
            }
        }
        // 更新
        if (len == INT_MAX) return 0;
        return len;
    }
};

http://www.kler.cn/news/326452.html

相关文章:

  • 计算机毕业设计 Java教务管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解
  • python魔法(python高级magic方法进阶)
  • 【北京迅为】《STM32MP157开发板嵌入式开发指南》- 第十五章 Linux 文件系统概念
  • 基于大数据的二手电子产品需求分析及可视化系统
  • open-resty 服务安装kafka插件
  • 深入理解EVM(以太坊虚拟机)及其工作原理,因为这将直接影响智能合约的开发。
  • 智融-SW6003 双向移动电源IC
  • P3131 [USACO16JAN] Subsequences Summing to Sevens S Python题解
  • idea使用技巧与插件推荐
  • 序列化方式五——ProtoStuff
  • JSON 教程
  • 什么Python库处理大量数据比较快?
  • Oracle 性能优化的高频面试题及答案
  • MySQL和Doris开窗函数LAG执行时的区别
  • PHP入门必看:从基础语法到实际应用,一文掌握Web开发的必备技能!
  • X-Spreadsheet:Web端Excel电子表格工具库
  • “AI+Security”系列第3期(五):AI技术在网络安全领域的本地化应用与挑战
  • 使用 Colly 在 Golang 中进行网页抓取的步骤
  • Rust Web自动化Demo
  • 《动手学深度学习》笔记2.4——神经网络从基础→进阶 (文件读写-保存参数和模型)
  • 堆的数组实现
  • nginx的安装和使用
  • 网页前端开发之Javascript入门篇(1/9):变量
  • 千益畅行,旅游创业新模式的创新与发展
  • 【Python报错已解决】ModuleNotFoundError: No module named ‘tensorflow‘
  • [每周一更]-(第117期):硬盘分区表类型:MBR和GPT区别
  • Windows开发工具使用技巧大揭秘:让编码效率翻倍的秘籍!
  • 软件设计之SSM(3)
  • SpringBoot中各种O的分层模型
  • 16 数组——18. 四数之和 ★★