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;
    }
};
相关推荐
Yingye Zhu(HPXXZYY)43 分钟前
ICPC 2023 Nanjing R L 题 Elevator
算法
苏小瀚3 小时前
[数据结构] ArrayList(顺序表)与LinkedList(链表)
数据结构
阿维的博客日记3 小时前
LeetCode 139. 单词拆分 - 动态规划解法详解
leetcode·动态规划·代理模式
程序员Xu4 小时前
【LeetCode热题100道笔记】二叉树的右视图
笔记·算法·leetcode
笑脸惹桃花4 小时前
50系显卡训练深度学习YOLO等算法报错的解决方法
深度学习·算法·yolo·torch·cuda
阿维的博客日记5 小时前
LeetCode 48 - 旋转图像算法详解(全网最优雅的Java算法
算法·leetcode
GEO_YScsn5 小时前
Rust 的生命周期与借用检查:安全性深度保障的基石
网络·算法
程序员Xu5 小时前
【LeetCode热题100道笔记】二叉搜索树中第 K 小的元素
笔记·算法·leetcode
THMAIL6 小时前
机器学习从入门到精通 - 数据预处理实战秘籍:清洗、转换与特征工程入门
人工智能·python·算法·机器学习·数据挖掘·逻辑回归
Kevinhbr6 小时前
CSP-J/S IS COMING
数据结构·c++·算法