Leetcode(239)——滑动窗口最大值

力扣239 - 滑动窗口的最大值【单调队列的原理】 对应力扣239 - 滑动窗口的最大值,带你搞懂单调队列的实现原理 阅读详情
AI摘要

本文详细解析了LeetCode第239题《滑动窗口最大值》的四种解法,包括优先队列+延迟删除、单调队列、分块+预处理以及平衡二叉排序树。每种方法都分析了时间复杂度和空间复杂度,重点介绍了单调队列和分块预处理的优化思路,以实现线性时间复杂度的解决方案。

Leetcode(239)——滑动窗口最大值

题目

给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。

返回 滑动窗口中的最大值。

示例 1:

输入:nums = [1,3,-1,-3,5,3,6,7], k = 3
输出:[3,3,5,5,6,7]
解释:
在这里插入图片描述

示例 2:

输入:nums = [1], k = 1
输出:[1]

提示:

  • 1 <= nums.length <= 105
  • -104 <= nums[i] <= 104
  • 1 <= k <= nums.length

题解

关键点:「随着窗口的移动实时维护最大值」——方法一和方法二

方法一:优先队列+延迟删除

思路

​​  对于维护「最大值」和「之前的最大值」,我们可以想到一种非常合适的数据结构和一种算法思想,那就是优先队列+延迟删除。其中的最大值优先队列可以帮助我们实时维护一系列元素中的最大值。类似 Leetcode 的第218题天际线。
​​  对于本题而言,初始时,我们将数组 nums\textit{nums}nums 的前 kkk 个元素放入优先队列中。每当我们向右移动窗口时,我们就可以把一个新的元素放入优先队列中,此时堆顶的元素就是堆中所有元素的最大值。然而这个最大值可能并不在滑动窗口中,在这种情况下,只需要判断这个最大值在数组 nums\textit{nums}nums 中的位置是否出现在滑动窗口左边界的左侧,是则是无效最大值,否则是有效最大值。因此,当我们后续继续向右移动窗口时,这个值就永远不可能出现在滑动窗口中了,我们可以将其永久地从优先队列中移除。
​​  我们不断地移除堆顶的元素,直到其确实出现在滑动窗口中。此时,堆顶元素就是滑动窗口中的最大值。为了方便判断堆顶元素与滑动窗口的位置关系,我们可以在优先队列中存储二元组 (num,index)(\textit{num}, \textit{index})(num,index),表示元素 num\textit{num}num 在数组中的下标为 index\textit{index}index。

代码实现
class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        priority_queue<pair<int, int>> max;
        int head=0, tail=k-1, last=nums.size()-1;
        for(int n=0; n<k; n++){
            max.emplace(nums[n], n);
        }
        vector<int> ans{max.top().first};    // 存储答案
        while(tail != last){
            head++;
            tail++;
            max.emplace(nums[tail], tail);
            // 找到有效的最大值
            while(head > max.top().second){
                max.pop();
            }
            ans.push_back(max.top().first);
        }
        return ans;
    }
};
复杂度分析

时间复杂度:O(nlog⁡n)O(n\log n)O(nlogn) ,其中 nnn 为数组的长度。该算法会遍历数组的每个数,为 O(n)O(n)O(n),而在最坏情况下,数组 nums\textit{nums}nums 中的元素单调递增,那么最终优先队列中包含了所有元素,没有元素被移除。由于将一个元素放入优先队列的时间复杂度为 O(log⁡n)O(\log n)O(logn),因此总时间复杂度为 O(nlog⁡n)O(n \log n)O(nlogn)。
空间复杂度:O(n)O(n)O(n) ,其中 nnn 为数组的长度。即为优先队列需要使用的空间。这里所有的空间复杂度分析都不考虑返回的答案需要的 O(n)O(n)O(n) 空间,只计算额外的空间使用。

方法二:单调队列

思路

​​  我们可以顺着方法一的思路继续进行优化某些操作——比如在方法一中每次窗口滑动时所需要的操作,即将一个元素放入优先队列操作的时间复杂度为 O(log⁡n)O(\log n)O(logn)。
​​  我们可以考虑使用单调队列,来使每次窗口滑动时所需要的操作的时间复杂度优化为 O(1)O(1)O(1)——单调队列入队和出队的时间复杂度为 O(1)O(1)O(1),进而实现算法的时间复杂度为 O(n)。

​​  关键点:

  • 由于我们需要求出的是滑动窗口的最大值,如果当前的滑动窗口中有两个值在数组中对应的下标是 iii 和 jjj,其中 iii 在 jjj 的左侧(i<ji < ji<j),并且 iii 对应的元素不大于 jjj 对应的元素(nums[i]≤nums[j]\textit{nums}[i] \leq \textit{nums}[j]nums[i]≤nums[j]),那么会发生什么呢?
  • 当滑动窗口向右移动时,只要 iii 还在窗口中,那么 jjj 一定也还在窗口中,这是 iii 在 jjj 的左侧所保证的。因此,由于 nums[j]\textit{nums}[j]nums[j] 还存在于滑动窗口中,所以 nums[i]\textit{nums}[i]nums[i] 一定不会是滑动窗口中的最大值了(因为 nums[i]\textit{nums}[i]nums[i] 会比 nums[j]\textit{nums}[j]nums[j] 要先离开滑动窗口),此时可以将 nums[i]\textit{nums}[i]nums[i] 永久地移除。

​​  算法实现:

  1. 因此我们可以使用一个双端队列存储所有还没有被移除的下标。在队列中,这些下标按照从小到大的顺序被存储,并且它们在数组 nums\textit{nums}nums 中对应的值是严格单调递减的,否则将被移除。
    因为如果队列中有两个相邻的下标,它们对应的值相等或者递增,那么令前者为 iii,后者为 jjj,就对应了上面所说的情况—— nums[i]\textit{nums}[i]nums[i] 会被移除,这就与实际情况产生了矛盾。
  2. 当滑动窗口向右移动时,我们需要把一个新的元素放入队列中。为了保持队列的性质,我们会不断地将新的元素与队尾的元素相比较,如果新的元素大于等于队尾的元素,那么队尾的元素就可以被永久地移除,我们将其从队尾弹出队列。我们需要不断地进行此项操作,直到队列为空或者新的元素小于队尾的元素。
  3. 由于队列中下标在数组 numsnumsnums 中对应的值是严格单调递减的,因此队首下标对应的元素“可能”(需要判断)就是滑动窗口中的最大值。但与方法一中相同的是,此时的最大值可能在滑动窗口左边界的左侧,并且随着窗口向右移动,它永远不可能出现在滑动窗口中了。因此我们还需要不断从队首弹出元素,直到队首元素在窗口中为止。
  4. 因此,算法中的单调队列的长度只需要等于 k (滑动窗口的长度) 即可。

举个例子: “543321” ,k=3

  • 队列存值的情况下,如果不将两个3都加入,当第一个3被移出时,会导致321的最大值变为2,因为3已经被移出了,因此存值的话,需要新的元素大于队列尾部元素再去移除队列尾部的元素。
  • 队列存下标的情况下,就可以只存一个3(存第二个),因为通过下标就能判断出移出的是第一个3还是第二个3。

例子:
输入:nums = [1,3,-1,-3,5,3,6,7], 和 k = 3
输出:[3,3,5,5,6,7]

解释过程中队列中都是具体的值,方便理解。
初始状态:L=R=0,队列:{}
i=0,nums[0]=1。队列为空,直接加入。队列:{1}
i=1,nums[1]=3。队尾值为1,3>1,弹出队尾值,加入3。队列:{3}
i=2,nums[2]=-1。队尾值为3,-1<3,直接加入。队列:{3,-1}。此时窗口已经形成,L=0,R=2,result=[3]
i=3,nums[3]=-3。队尾值为-1,-3<-1,直接加入。队列:{3,-1,-3}。队首3对应的下标为1,L=1,R=3,有效。result=[3,3]
i=4,nums[4]=5。队尾值为-3,5>-3,依次弹出后加入。队列:{5}。此时L=2,R=4,有效。result=[3,3,5]
i=5,nums[5]=3。队尾值为5,3<5,直接加入。队列:{5,3}。此时L=3,R=5,有效。result=[3,3,5,5]
i=6,nums[6]=6。队尾值为3,6>3,依次弹出后加入。队列:{6}。此时L=4,R=6,有效。result=[3,3,5,5,6]
i=7,nums[7]=7。队尾值为6,7>6,弹出队尾值后加入。队列:{7}。此时L=5,R=7,有效。result=[3,3,5,5,6,7]

代码实现
class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        deque<int> monotone_queue;  // 单调队列。存储下标,既方便取值,又方便判断是不是有效最大值
        // 准备阶段
        for(int n=0; n<k; n++){
            while(!monotone_queue.empty() && nums[monotone_queue.back()] <= nums[n])
                monotone_queue.pop_back();
            monotone_queue.push_back(n);
        }
        vector<int> ans{nums[monotone_queue.front()]};
        int length = nums.size(), n=k;
        while(n != length){
            // 插入新值
            while(!monotone_queue.empty() && nums[monotone_queue.back()] <= nums[n])
                monotone_queue.pop_back();
            monotone_queue.push_back(n);
            // 清理无效最大值
            while(!monotone_queue.empty() && monotone_queue.front() <= n-k)
                monotone_queue.pop_front();
			// 经历两个步骤(插入新值,清理无效最大值)后
			// 此时单调队列 monotone_queue.front() 中的就是滑动窗口右移后的新最大值的下标
            ans.push_back(nums[monotone_queue.front()]);
            n++;
        }
        return ans;
    }
};
复杂度分析

时间复杂度:O(n)O(n)O(n),其中 nnn 为数组 nums\textit{nums}nums 的长度。和方法一一样,每一个下标恰好被放入队列一次,并且最多被弹出队列一次,但是这次一个下标放入队列的时间复杂度为 O(1)O(1)O(1),所以时间复杂度为 O(n)O(n)O(n)。
空间复杂度:O(k)O(k)O(k),其中 kkk 是滑动窗口大小。与方法一不同的是,在方法二中我们使用的数据结构是双向的,因此「不断从队首弹出元素」保证了队列中最多不会有超过 k+1k+1k+1 个元素,因此队列使用的空间为 O(k)O(k)O(k)。这里所有的空间复杂度分析都不考虑返回的答案需要的 O(n)O(n)O(n) 空间,只计算额外的空间使用。

方法三:分块 + 预处理

思路

​​  除了基于「随着窗口的移动实时维护最大值」的方法一以及方法二之外,我们还可以考虑其他有趣的做法。

​​  我们可以将数组 nums\textit{nums}nums 从左到右按照 kkk 个一组进行分组,最后一组中元素的数量可能会不足 kkk 个。如果我们希望求出 nums[i]\textit{nums}[i]nums[i] 到 nums[i+k−1]\textit{nums}[i+k-1]nums[i+k−1] 的最大值,就会有两种情况:

  • 如果 iii 是 kkk 的倍数,那么 nums[i]\textit{nums}[i]nums[i] 到 nums[i+k−1]\textit{nums}[i+k-1]nums[i+k−1] 恰好是一个分组。我们只要预处理出每个分组中的最大值,即可得到答案;
  • 如果 iii 不是 kkk 的倍数,那么 nums[i]\textit{nums}[i]nums[i] 到 nums[i+k−1]\textit{nums}[i+k-1]nums[i+k−1]] 会跨越两个分组,占有第一个分组的后缀以及第二个分组的前缀。假设 jjj 是 kkk 的倍数,并且满足 i<j≤i+k−1i < j \leq i+k-1i<j≤i+k−1,那么 nums[i]\textit{nums}[i]nums[i] 到 nums[j−1]\textit{nums}[j-1]nums[j−1] 就是第一个分组的后缀,nums[j]\textit{nums}[j]nums[j] 到 nums[i+k−1]\textit{nums}[i+k-1]nums[i+k−1] 就是第二个分组的前缀。如果我们能够预处理出每个分组中的前缀最大值以及后缀最大值,同样可以在 O(1)O(1)O(1) 的时间得到答案。

算法实现:

因此我们用 prefixMax[i]\textit{prefixMax}[i]prefixMax[i] 表示下标 iii 对应的分组中,以 iii 结尾的前缀最大值;suffixMax[i]\textit{suffixMax}[i]suffixMax[i] 表示下标 iii 对应的分组中,以 iii 开始的后缀最大值。它们分别满足如下的递推式
prefixMax[i]={nums[i],i 是 k 的倍数max⁡{prefixMax[i−1],nums[i]},i 不是 k 的倍数​ \textit{prefixMax}[i]=\begin{cases} \textit{nums}[i], & \quad i ~是~ k ~的倍数 \\ \max\{ \textit{prefixMax}[i-1], \textit{nums}[i] \}, & \quad i ~不是~ k ~的倍数 \end{cases} ​prefixMax[i]={nums[i],max{prefixMax[i−1],nums[i]},​i 是 k 的倍数i 不是 k 的倍数​​​
以及
suffixMax[i]={nums[i],i+1 是 k 的倍数max⁡{suffixMax[i+1],nums[i]},i+1 不是 k 的倍数 \textit{suffixMax}[i]=\begin{cases} \textit{nums}[i], & \quad i+1 ~是~ k ~的倍数 \\ \max\{ \textit{suffixMax}[i+1], \textit{nums}[i] \}, & \quad i+1 ~不是~ k ~的倍数 \end{cases} suffixMax[i]={nums[i],max{suffixMax[i+1],nums[i]},​i+1 是 k 的倍数i+1 不是 k 的倍数​
需要注意在递推 suffixMax[i]\textit{suffixMax}[i]suffixMax[i] 时需要考虑到边界条件 suffixMax[n−1]=nums[n−1]\textit{suffixMax}[n-1]=\textit{nums}[n-1]suffixMax[n−1]=nums[n−1],而在递推 prefixMax[i]\textit{prefixMax}[i]prefixMax[i] 时的边界条件 prefixMax[0]=nums[0]\textit{prefixMax}[0]=\textit{nums}[0]prefixMax[0]=nums[0] 恰好包含在递推式的第一种情况中,因此无需特殊考虑。

在预处理完成之后,对于 nums[i]\textit{nums}[i]nums[i] 到 nums[i+k−1]\textit{nums}[i+k-1]nums[i+k−1] 的所有元素,如果 iii 不是 kkk 的倍数,那么窗口中的最大值为 suffixMax[i]\textit{suffixMax}[i]suffixMax[i] 与 prefixMax[i+k−1]\textit{prefixMax}[i+k-1]prefixMax[i+k−1] 中的较大值;如果 iii 是 kkk 的倍数,那么此时窗口恰好对应一整个分组,suffixMax[i]\textit{suffixMax}[i]suffixMax[i] 和 prefixMax[i+k−1]\textit{prefixMax}[i+k-1]prefixMax[i+k−1] 都等于分组中的最大值,因此无论窗口属于哪一种情况,
max⁡{suffixMax[i],prefixMax[i+k−1]} \max\big\{ \textit{suffixMax}[i], \textit{prefixMax}[i+k-1] \big\} max{suffixMax[i],prefixMax[i+k−1]}
即为答案。
这种方法与稀疏表(Sparse Table)非常类似,感兴趣的读者可以自行查阅资料进行学习。

代码实现
class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        int n = nums.size();
        vector<int> prefixMax(n), suffixMax(n);
        for (int i = 0; i < n; ++i) {
            if (i % k == 0) {
                prefixMax[i] = nums[i];
            }
            else {
                prefixMax[i] = max(prefixMax[i - 1], nums[i]);
            }
        }
        for (int i = n - 1; i >= 0; --i) {
            if (i == n - 1 || (i + 1) % k == 0) {
                suffixMax[i] = nums[i];
            }
            else {
                suffixMax[i] = max(suffixMax[i + 1], nums[i]);
            }
        }

        vector<int> ans;
        for (int i = 0; i <= n - k; ++i) {
            ans.push_back(max(suffixMax[i], prefixMax[i + k - 1]));
        }
        return ans;
    }
};
复杂度分析

时间复杂度:O(n)O(n)O(n),其中 nnn 为数组 numsnumsnums 的长度。我们需要 O(n)O(n)O(n) 的时间预处理出数组 prefixMax\textit{prefixMax}prefixMax, suffixMax\textit{suffixMax}suffixMax 和计算答案。
空间复杂度:O(n)O(n)O(n),其中 nnn 为存储 prefixMax\textit{prefixMax}prefixMax 和 suffixMax\textit{suffixMax}suffixMax 需要的空间。这里所有的空间复杂度分析都不考虑返回的答案需要的 O(n)O(n)O(n) 空间,只计算额外的空间使用。


方法四:平衡二叉排序树

时间复杂度和空间复杂度都比前三个方法高

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        // 整数数组长为l,窗口长度为k,滑动窗口中的最大值有l-k+1个
        // 两个问题:1.更新滑动窗口的内容 2.维护滑动窗口的最大值
        // 1.用队列(C++ 的双端队列)保存滑动窗口的内容————————优化,不需要队列,使用数组下标来保持
        // 2.用 map 来维护滑动窗口的最大值———— pair<值,个数>
        map<int, int> max;          // pair<值,个数>
        int front = 0,back = k-1;   // 使用数组下标和输入数组来实现队列
        int l = nums.size();
        // 准备阶段
        for(int n = 0; n<k; n++){
            if(max.find(nums[n]) == max.end()){
                max.insert({nums[n], 1});    // 不存在该值
            }else max[nums[n]] += 1;
        }
        vector<int>  ans{max.crbegin()->first};

        int head,newone; // 用于保存队列的队首和下一个进队列的值
        while(back != l-1){
            head = nums[front];
            newone = nums[++back];
            if(max[head] == 1){
                max.erase(head);          // 该值只有一个,直接删除
            }else max[head] -= 1;   // 该值不止一个,递减

            if(max.find(newone) == max.end()){
                max.insert({newone, 1});    // 不存在该值
            }else max[newone] += 1;

            ans.push_back(max.crbegin()->first);
            front++;
        }
        return ans;
    }
};
关于滑动窗口最大值 有读者小伙伴建议讲一下滑动窗口相关题型,因为经常面试会被问到。所以就开了这个系列(所以如果大家有想让分享的题型都可以留言区告诉我,任何事情我觉得都需要有反馈。比如一个错误,你不反馈,我不知道…那就只能这样过去了…)闲话不啰嗦,直接看题! 01、题目分析 第239题:滑动窗口最大值 给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。返回滑动窗口中的最大值。 给定一个数组 nums,有. 阅读详情

相关推荐

LeetCode 239. 滑动窗口最大值【c++/java详细题解】

目录1、题目2、思路3、c++代码4、java代码 1、题目 给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回滑动窗口中的最大值。 示例 1: 输入:nums = [1,3,-1,-3,5,3,6,7], k = 3 输出:[3,3,5,5,6,7] 解释: 滑动窗口的位置 最大值 --------------- ----- [1

林深不见鹿 的博客 2689

滑动窗口最大值

滑动窗口最大值 题目链接 方法1:暴力求解: 对于每个滑动窗口,我们可以使用 O(k) 的时间遍历其中的每一个元素,找出其中的最大值。 对于长度为 n 的数组 nums ,窗口的数量为 n-k+1 因此该算法的时间复杂度为 O((n-k+1)k)=O(nk),会超出时间限制,需要进行一些优化。 暴力优化: 滑动窗口特点就是每次移动,会出一个元素,进一个元素。 也就是说它们共用着 k-1个元素,而只有 1 个元素是变化的。我们可以根据这个特点进行优化。 首先最容易想到的就是去维护一个最大值,窗口每滑动一次,

Better_WZQ的博客 7450

Leetcode 239 滑动窗口最大值

给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口 k 内的数字。滑动窗口每次只向右移动一位。 返回滑动窗口最大值。 示例: 输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3 输出: [3,3,5,5,6,7] 解释: 滑动窗口的位置 最大值 [1 3 -1] -3 5 ...

万万没想到的博客 1692

【Leetcode刷题Python】239. 滑动窗口最大值

给定一个数组 nums 和滑动窗口的大小 k,请找出所有滑动窗口里的最大值。示例:输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3 输出: [3,3,5,5,6,7](1)方法一:大堆树对于本题而言,初始时,我们将数组 nums 的前 k个元素放入优先队列中。每当我们向右移动窗口时,我们就可以把一个新的元素放入优先队列中,此时堆顶的元素就是堆中所有元素的最大值。 然而这个最大值可能并不在滑动窗口中,在这种情况下,这个值在数组 nums 中的位置出现在滑动窗口左边界的左侧。因此,

BetterBench的博客 3033

cut&tag学习笔记

上图是我得到的结果,下图是教程的结果,比对结果有一些差异,我也不知道具体原因是啥。谷歌了一下,发现原因可能是因为环境变量的问题,系统不知道picard的具体位置,需要设置全局环境变量,遂查了一下picard的位置。我发现我做出来的结果测序深度一致,但是比对的结果有一点差异,不知道是我的操作问题,还是参考基因组更新了导致比对结果出现了些许不同。上图是我得到的结果,下图是教程的结果,除了IgG_rep1外比对结果一致。上图是我的结果,下图是教程的结果,结果不太一致,不知道是具体的原因是什么。

weixin_52073820的博客 2422

多目标跟踪(MOT)中的卡尔曼滤波(Kalman filter)和匈牙利(Hungarian)算法详解

多目标跟踪(MOT)中的卡尔曼滤波(Kalman filter)和匈牙利(Hungarian)算法详解 1. 概览 在开始具体讨论卡尔曼滤波和匈牙利算法之前,首先我们来看一下基于检测的目标跟踪算法的大致流程。 2. 卡尔曼滤波(Kalman filter) 目标跟踪中使用的就是最基础的 Kalman filter 算法。这里也仅仅讨论最基础的 Kalman filter 算法。 卡尔曼滤波算法的过程很简单,如下图所示。最核心的两个步骤就是预测和更新(下图的 correct)。 在目标跟踪任务中,目标的

生命在于折腾! 2万+

力扣(LeetCode)100题:239.滑动窗口最大值

摘要:本文详细解析了LeetCode 239题「滑动窗口最大值」的两种解法。暴力解法采用双重循环遍历窗口元素求最大值,时间复杂度为O(nk)。优化解法包括:1)优先队列(最大堆),通过存储负值和索引实现,时间复杂度O(nlogn);2)单调队列(最优解),维护递减队列保证队首始终为当前窗口最大元素,时间复杂度O(n)。两种优化解法都通过详细注释和示例演示了算法流程,并分析了复杂度。其中单调队列解法空间复杂度O(k),是理论最优解。文章对比了不同解法的性能差异,并总结了关键实现技巧。

sweet_ran的博客 1073

华硕ROG枪神双系统实战:Ubuntu安装避坑指南

本文是华硕ROG枪神笔记本安装Ubuntu双系统的详细避坑指南。针对其独特的硬件与BIOS设计,文章核心解决了VMD控制器导致硬盘无法识别、驱动兼容性等关键难题,并提供了从BIOS设置、分区方案到安装后驱动配置与性能调优的一站式解决方案,帮助用户实现稳定的双系统体验。

raspberrypi5的博客 545

【困难】力扣算法题解析LeetCode239:滑动窗口最大值

题目要求实现滑动窗口最大值,给定数组和窗口大小k,返回每个窗口的最大值序列。采用单调队列优化,核心思路是维护一个双端队列存储索引,确保队首始终为当前窗口最大值。遍历时移除过期元素并保持队列单调递减。Java代码通过双端队列动态维护窗口最大值,高效解决问题

ylumwd的博客 872

LTspice元器件库导入与路径管理:符号、模型、子电路全解析

在电子电路仿真中,元器件库通常由符号、模型和子电路三层构成:符号定义引脚外观,模型描述电气行为,子电路封装多端子网络。理解三者职责边界,是解决 LTspice 元器件库导入报错的关键。许多导入失败并非软件问题,而是文件类型错配、路径引用不清或引脚顺序不一致。掌握 `.include` 指令、用户库搜索路径和自制符号绑定模型,可以提升第三方模型复用效率,降低跨项目迁移成本。该思路适用于运放、MOS 管、二极管等器件建模,尤其在 UA741 等经典运放导入场景中,需要先核对 `.subckt` 引脚顺序,再选择

weixin_29182481的博客 178

Python多进程实战:用BaoStock高效下载股票历史数据的5个优化技巧

本文详细介绍了使用Python多进程技术通过BaoStock高效下载股票历史数据的5个优化技巧。从理解BaoStock的数据获取机制到进程池配置、智能任务分片、异常处理及性能监控,帮助开发者显著提升数据下载效率,特别适合量化交易领域的数据采集需求。

weixin_30369041的博客 454

【滑动窗口】力扣239.滑动窗口最大值

滑动窗口——窗口内的最大值

weixin_46879314的博客 1281

实战Nocobase插件开发:如何用yarn pm命令快速创建和测试API接口插件

本文详细介绍了如何使用Nocobase插件开发工具快速创建和测试API接口插件,涵盖从环境配置、插件骨架生成到数据模型定义和接口实现的完整流程。通过yarn pm命令简化开发步骤,帮助开发者高效构建支持CRUD的API插件,适用于低代码平台开发场景。

weixin_29313239的博客 456

力扣:239.滑动窗口最大值

力扣:239.滑动窗口最大值 题目链接 给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回 滑动窗口中的最大值 。 示例 1: 输入:nums = [1,3,-1,-3,5,3,6,7], k = 3 输出:[3,3,5,5,6,7] 解释: 滑动窗口的位置 最大值 [1 3 -1] -3 5 3 6 7 3 1 [3 -1 -3] 5

meraki的博客 261

RT-DETR算法优化改进:轻量级上采样CARAFE算子 | 注意力机制大作战

上采样操作CARAFE,具有感受野大、内容感知、轻量级、计算速度快等优点,引入RT-DETR二次创新;1)代替Upsample进行使用;

①答疑群聊服务;②YOLO大模型知识问答系统;③计算机视觉论文生成智能体; 1265

全新DEIM有效涨点改进目录 | 本专栏持续更新500+篇内容 | 包含各种顶会顶刊卷积、注意力、特征融合模块、有效特征聚合提取模块,上采样模块、下采样模块,二次创新模块、独家创新等几百种创新点改进

🚀【CVPR2025DEIM改进专栏速览】🔥 专栏提供500+篇目标检测创新改进方案,涵盖卷积/注意力/特征融合等创新改进点,均源自顶会论文及实战经验。支持多领域应用(工业/医疗/遥感等),配套完整教程和答疑服务。亮点包括: 1️⃣ 持续更新SOTA模型改进方案 2️⃣ 小白友好型实验操作指南 3️⃣ 跨学科科研支持(已助非计算机专业发表论文) 4️⃣ 提供虚拟环境配置方案。 订阅可获完整项目代码及交流群服务,适合研究生科研论文改进需求。价格呈上涨趋势,早订更优惠!

Ai缝合怪、助力小伙伴高效发论文 2034

力扣239题详解:滑动窗口最大值的多种解法与模拟面试问答

本文详细解读了力扣第239题“滑动窗口最大值”,通过使用双端队列高效地计算数组中每个滑动窗口的最大值,并提供了详细的解释和模拟面试问答。希望读者通过本文的学习,能够在力扣刷题的过程中更加得心应手。

10年数据\经营分析经验,现任大厂数据分析负责人 2302

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

【算法入门】LeetCode 239. 滑动窗口最大值:Java与JavaScript双解法详解|单调队列的精妙运用力扣239题详解:滑动窗口最大值(Java & JavaScript 双语言实现)

通过本文,我们学习了如何使用Java和JavaScript解决滑动窗口最大值问题。使用双端队列来维护窗口中的最大值是一种有效的方法,它允许我们在O(n)的时间复杂度内完成整个数组的遍历。希望这篇文章能帮助你更好地理解并掌握这一知识点。好的,我很乐意为你提供详细的解答和博客内容。以下是一篇新手入门博客,包含Java和JavaScript的解答以及相关知识点的详细介绍。博客标题: 从零开始学习力扣题 239. 滑动窗口最大值目录:问题描述Java解答2.1 使用双端队列JavaScript解答。

南北极之间 1180

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

LeetCode 239 滑动窗口最大值

LeetCode 239 滑动窗口最大值 题目链接 给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回滑动窗口中的最大值。 示例 1: 输入:nums = [1,3,-1,-3,5,3,6,7], k = 3 输出:[3,3,5,5,6,7] 解释: 滑动窗口的位置 最大值 --------------- ----- [1 3 -1]

旺崽的博客 3081

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

239. 滑动窗口最大值 - 力扣(LeetCode)

假设输入数组为 nums = [1, 3, -1, -3, 5, 3, 6, 7],k = 3。移除 deque 中所有小于 5 的元素(3, -1, -3),deque 变为空。的滑动窗口从数组的最左侧移动到数组的最右侧。窗口形成,记录 7 → res = [3, 3, 5, 5, 6, 7]。输入:nums = [1,3,-1,-3,5,3,6,7], k = 3。窗口形成,记录 6 → res = [3, 3, 5, 5, 6]。最终结果 res 为 [3, 3, 5, 5, 6, 7]。

q1111111da的博客 751

golang力扣leetcode 239.滑动窗口最大值

239.滑动窗口最大值239.滑动窗口最大值题解代码 239.滑动窗口最大值 239.滑动窗口最大值 题解 题目:给一个数组,再给一个k大小的滑动窗口,求窗口内的最大值 思路:优先队列 和 单调栈 1.维护一个单调递减队列 2.对于窗口右移,就是往队列中插入,与删除 3.而删除需要遍历,但是本题其实不急着删除,即延迟删除 4.也就是说当nums[i-k] == queue[0]的时候,就可以删除,这样就是O(1) 5.对于插入,需要维护递减,如果插入v大于下面的,则弹出下面的即可 例如:[5,6,1,2]3

清风 831

leetcode 239.滑动窗口最大值(python)

leetcode 239.滑动窗口最大值(python) 给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回滑动窗口中的最大值。 进阶: 你能在线性时间复杂度内解决此题吗? 示例: 输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3 输出: [3,3,5,5,6,7] 解释: 滑动窗口的位置 最大值 ---------------

pureszgd的博客 1210

LeetCode 239:滑动窗口最大值

给定整数数组nums和窗口大小k,需返回。

m0_75126572的博客 911

LeetCode 239. 滑动窗口最大值

给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回 滑动窗口中的最大值 。

2301_80211119的博客 1387

leetcode:239. 滑动窗口最大值

题目解析 题目相当于维护了一个大小为3的滑动窗口,并输出每个滑动窗口内的最大值那么什么是滑动窗口呢?举个例子,我们从数组中第一个元素开始遍历,由于窗口的大小是333,因此当遍历到第三个元素时候窗口就形成了 之后,继续遍历元素,为了保持窗口的大小为3,左侧元素就需要从窗口中剔除。这样就使得窗口一直向右移动,直到考察到最后一个元素结束,这就是所谓的滑动窗口。怎么实现呢?我们分别维护两个变量L,R为表示一个窗口。那么,应该怎么滑动呢?令N = arr.size()维护一个滑动窗口并不难,但是我们需要解决一个问题:

OceanStar的博客 1302

LeetCode239. 滑动窗口最大值

LeetCode239. 滑动窗口最大值

Love Peace 525
上一篇: 关于优先队列在算法中的使用(通常结合延迟删除)——也是延迟删除思想的学习
下一篇: Leetcode(1)——两数之和
486L
博客等级 码龄7年 20粉丝 117原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值