首页 > 其他分享 >剑指 Offer 59 - I. 滑动窗口的最大值 - 力扣(Leetcode)

剑指 Offer 59 - I. 滑动窗口的最大值 - 力扣(Leetcode)

时间:2022-11-13 11:26:21浏览次数:88  
标签:59 Offer int 复杂度 nums vector 数组 ans Leetcode

剑指 Offer 59 - I. 滑动窗口的最大值 - 力扣(Leetcode)

一.分析

方法一:

数组长度为1e5,k的大小为1e4,因此直接暴力计算会TLE。我们可以思考一个更复杂的问题:询问任意区间中的最值。对于该题,可以等价询问数组长度次的最值,如果能将每次询问的复杂度控制在logN以内,就可以解决该问题。
而对于区间最值我们可以使用线段树(logN),树状数组(logNlogN),稀疏数组(1)等数据结构。

  1. 树状数组
树状数组
class Solution {
public:
    int b[100005];
    int n;
    const int inf=-0x3f3f3f3f;
    int lowbit(int x)
    {
        return x&(-x);
    }
    void update(int pos,vector<int>& a)
    {
        while(pos<=n)
        {
            b[pos]=a[pos-1];
            for (int i=1;i<lowbit(pos);i<<=1)
            {
                b[pos]=max(b[pos],b[pos-i]);
            }
            pos+=lowbit(pos);
        }
    }
    int query(int l,int r,vector<int>& a)
    {
        int ans=inf;
        while(l<=r)
        {
            ans=max(ans,a[r-1]);
            r--;
            while (l<=r-lowbit(r))
            {
                ans=max(ans,b[r]);
                r-=lowbit(r);
            }
        }
        return ans;
    }
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        n=nums.size();
        vector<int> ans;
        for (int i=1;i<=n;i++)
        {
            b[i]=inf;
        }
        for (int i=0;i<nums.size();i++)
        {
            update(i+1,nums);
        }
        // for (int i=1;i<=n;i++)
        // {
        //     cout<<b[i]<<" ";
        // }
        for (int i=k;i<=n;i++)
        {
            ans.push_back(query(i-k+1,i,nums));
        }
        return ans;
    }
};
  1. 稀疏数组
稀疏数组
class Solution {
public:
    const int static maxn=200005;
    int st[maxn][17];
    int Log2[maxn];
    int n;
    void init()
    {
        for (int i=1;i<n+10;i++)
            Log2[i]=Log2[i>>1]+1;
    }
    void prepro(vector<int>& nums)
    {
        for (int i=0;i<n;i++)
            st[i][0]=nums[i];
        //cout<<st[2][0]<<endl;
        for (int i=1;i<=Log2[n-1];i++)
        {
            for (int j=0;j<=n-(1<<i);j++)
            {
                st[j][i]=max(st[j][i-1],st[j+(1<<(i-1))][i-1]);
            }
        }
    }
    int query(int l,int r)
    {
        // cout<<l<<"----"<<r<<endl;
        // cout<<Log2<<endl;
        return max(st[l][Log2[r-l+1]-1],st[1+r-(1<<(Log2[r-l+1]-1))][Log2[r-l+1]-1]);
    }
    vector<int> maxSlidingWindow(vector<int>& nums, int k) { 
        n=nums.size();
        init();
        //cout<<st[2][0]<<endl;
        prepro(nums);
        vector<int> ans;
        for (int i=0;i<n-k+1;i++)
        {
            ans.push_back(query(i,i+k-1));
        }
        //ans.push_back(query(2,4));
        return ans;
    }
};

方法二:

考虑滑动窗口向右移动过程中下标为i和j的元素,i<j, 若nums[i] < nums[j],那么num[i]就不可能是滑动窗口中的最大值了。因为若i在滑动窗口中,那么j肯定在滑动窗口中。因此可以维护一个双向队列,当向右移动时,添加元素应该保证队列的严格单调递减(如违反,则从队尾删除元素,类似单调栈)。同时还要保证队列中的元素在滑动窗口中,若不在,从队头删除元素。
复杂度分析:数组中的每个元素都入队一次,出队一次,时间复杂度为O(n),空间复杂度为双向队列的长度O(k)

双向队列
class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        deque<pair<int,int>> q;
        vector<int> ans;
        for (int i=0;i<nums.size();i++)
        {
            while (q.size() and q.back().second<nums[i])
            {
                q.pop_back();
            }
            q.push_back(pair(i,nums[i]));
            while (q.size() and q.front().first<i-k+1)
            {
                q.pop_front();
            }
            if (i>=k-1)
                ans.push_back(q.front().second);
        }
        return ans;
    }
};

标签:59,Offer,int,复杂度,nums,vector,数组,ans,Leetcode
From: https://www.cnblogs.com/sjw-blogs/p/16885617.html

相关文章

  • 白嫖永久服务器1668309595005
    阿贝云服务器注册免费领取1核1g内存5m宽带10g内存的云服务器,对于个人来说完全够用了。还有免费备案和虚拟主机,免备案对于搭建个人博客就很方便,部署了小项目上去,运行流畅不......
  • [回溯算法]leetcode40. 组合总和 II(c实现)
    题目给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。candidates 中的每个数字在每个组合中......
  • leetcode 647. 回文子串 js实现
    给你一个字符串 s ,请你统计并返回这个字符串中 回文子串 的数目。回文字符串 是正着读和倒过来读一样的字符串。子字符串 是字符串中的由连续字符组成的一个序列。......
  • LeetCode 665. 非递减数列
    classSolution{public:boolcheckPossibility(vector<int>&nums){intn=nums.size();for(inti=0;i<n-1;i++){intx=nums[i......
  • LeetCode刷题记录.Day13
    四数之和18.四数之和-力扣(LeetCode)classSolution{public:vector<vector<int>>fourSum(vector<int>&nums,inttarget){vector<vector<int>>res......
  • #yyds干货盘点# LeetCode 腾讯精选练习 50 题:最小栈
    题目:设计一个支持push,pop,top操作,并能在常数时间内检索到最小元素的栈。实现MinStack类:MinStack()初始化堆栈对象。voidpush(intval)将元素val推入堆栈。voidpop......
  • leetcode-888-easy
    FairCandySwapAliceandBobhaveadifferenttotalnumberofcandies.YouaregiventwointegerarraysaliceSizesandbobSizeswherealiceSizes[i]isthenum......
  • leetcode-1486-easy
    XOROperationinanArrayYouaregivenanintegernandanintegerstart.Defineanarraynumswherenums[i]=start+2*i(0-indexed)andn==nums.length......
  • Leetcode第790题:多米诺和托米诺平铺(Domino and tromino tiling)
    解题思路采用动态规划思路。参考题解。核心代码如下:constlonglongmod=1e9+7;classSolution{public:intnumTilings(intn){vector<vector<lo......
  • leetcode-2047-easy
    NumberofValidWordsinaSentenceAsentenceconsistsoflowercaseletters('a'to'z'),digits('0'to'9'),hyphens('-'),punctuationmarks('!','.',and......