Leetcode209-长度最小的子数组[两种方法] 关键词 滑窗 二分答案 前缀和

文章目录

  • 前言
  • 题目
  • [方法一:滑窗 O(n)](#方法一:滑窗 O(n))
  • [方法二:二分答案 O(nlogn)](#方法二:二分答案 O(nlogn))

前言

  1. 左闭右开是编程中表示一段区间的最规范的方式
  2. 二分查找的正确打开方式为
cpp 复制代码
        int lo = 0, hi = n, mi;
        while (lo < hi) {
            mi = (lo + hi) / 2;
            if (k < sum[mi])
                hi = mi;
            else
                lo = mi + 1;
        }
        return lo - 1;
  1. O(nlogn)的算法不一定比O(n)的算法慢

题目


方法一:滑窗 O(n)

滑窗处理"最长子列"问题,就是左端在迫不得已的时候才收缩;

滑窗处理"最短子列"问题,就是左端积极收缩,只要有能使窗口变小的可能,就积极尝试。

本题就是后者:滑窗右端每向右挪一个元素,尝试收缩左端。

cpp 复制代码
class Solution {
    int sum = 0; // 滑窗内的数值总和
    int min(int a, int b) { return a < b ? a : b; }

public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int pl = 0, pr = 0, ans = 200000;
        // [pl, pr)左闭右开区间
        while (pr < nums.size()) {
            sum += nums[pr];
            pr++;

            if (sum < target)
                continue;

            while (sum - nums[pl] >= target) {
                sum -= nums[pl];
                pl++;
            }
            ans = min(ans, pr - pl);
        }
        return ans == 200000 ? 0 : ans;
    }
};

方法二:二分答案 O(nlogn)

预处理好前缀和之后,对于每一个右边界,二分找到对应的左边界。

cpp 复制代码
class Solution {
    int sum[100010]; // 前缀和
    int min(int a, int b) { return a < b ? a : b; }
    int find(int n, int k) // n个元素,返回值小于等于k的最后一个元素的下标
    {
        int lo = 0, hi = n, mi; // lo hi左闭右开
        while (lo < hi) {
            mi = (lo + hi) / 2;
            if (k < sum[mi])
                hi = mi;
            else
                lo = mi + 1;
        }
        return lo - 1;
    }

public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int pl = 0, pr = 0, ans = 200000;
        sum[0] = 0;
        for (int i = 0; i < nums.size(); i++)
            sum[i + 1] = sum[i] + nums[i];

        for (int i = 1; i < nums.size() + 1; i++) {
            int pos = find(nums.size() + 1, sum[i] - target);
            if (pos < 0)
                continue;
            ans = min(ans, i - pos);
        }

        return ans == 200000 ? 0 : ans;
    }
};
相关推荐
程序员-King.5 小时前
day158—回溯—全排列(LeetCode-46)
算法·leetcode·深度优先·回溯·递归
星火开发设计6 小时前
C++ 数组:一维数组的定义、遍历与常见操作
java·开发语言·数据结构·c++·学习·数组·知识
月挽清风6 小时前
代码随想录第七天:
数据结构·c++·算法
小O的算法实验室6 小时前
2026年AEI SCI1区TOP,基于改进 IRRT*-D* 算法的森林火灾救援场景下直升机轨迹规划,深度解析+性能实测
算法·论文复现·智能算法·智能算法改进
小郭团队7 小时前
2_1_七段式SVPWM (经典算法)算法理论与 MATLAB 实现详解
嵌入式硬件·算法·硬件架构·arm·dsp开发
充值修改昵称7 小时前
数据结构基础:从二叉树到多叉树数据结构进阶
数据结构·python·算法
Deepoch7 小时前
Deepoc数学大模型:发动机行业的算法引擎
人工智能·算法·机器人·发动机·deepoc·发动机行业
-To be number.wan8 小时前
【数据结构真题解析】哈希表中等难度挑战:冲突处理与查找效率深度剖析
数据结构·哈希算法
csdn_aspnet8 小时前
C 语言的优雅回归:从零手造数据结构
c语言·数据结构