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;
    }
};
相关推荐
wuyk55517 分钟前
98.C语言易混难点:字符数组与字符串指针的底层差异
c语言·开发语言·c++·stm32·嵌入式硬件·算法
峥无35 分钟前
从0到1手撕红黑树:封装实现 my_map 与 my_set(SGI-STL 源码级深度解析)
开发语言·c++·笔记·算法·stl
不会代码的小猴1 小时前
3. 控件学习1
开发语言·c++·笔记·qt·算法
疯狂打码的少年3 小时前
【数据结构】图的存储结构:邻接矩阵与邻接表
数据结构·笔记
203号居民3 小时前
LeetCode hot 100 —41. 缺失的第一个正数
数据结构·算法·leetcode
专注仿真5 小时前
问答大模型技术方案算法实现-熵权法融合算法 + 交叉编码器重排算法
人工智能·python·算法·语言模型·问答大模型关键算法·熵权融合算法·交叉编码器重排算法
地平线开发者6 小时前
量化为什么会有损失:从量化误差到精度下降
算法
手写码匠7 小时前
华为云Flexus+DeepSeek征文|Dify 多 Agent 会话管理与上下文工程实战:让智能体“记住该记住的,忘掉该忘掉的“
人工智能·深度学习·算法·aigc
2401_862880827 小时前
数据结构 --- 栈
c语言·数据结构·算法