leetcode刷题笔记239

写在前边

这是一道hard的题目,但是我觉得没有想象的那么难,大概在中等难度,主要是要搞清楚一些东西,譬如优先级队列等,还有一点比较重要的需要搞清楚,我会在下边提及,这道题不仅仅是让我学到算法,也让我重视起对于stl的使用。

题目

给你一个整数数组 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 3 6 7 3
1 3 [-1 -3 5] 3 6 7 5
1 3 -1 [-3 5 3] 6 7 5
1 3 -1 -3 [5 3 6] 7 6
1 3 -1 -3 5 [3 6 7] 7

题目描述看起来有些长,总结就是,用一个“方框”去套住数组中的数字,把那个方框中最大的数作为结果压入一个vector,把这个“方框”依次往后移,直到把数组中的每个数都遍历一遍,得到的vector就是答案。

这道题很容易用暴力解法做,相信每一个学过计算机编程语言的人都知道,只需要判断出下标i到i+k之间的最大值,将其压入vector即可,但是这样做肯定是不行的,时间复杂度太高了。

因此需要一些改进,对于我本人的改进方法是:将每一个“方框”中的数做成最大堆,这样就能得出每个方框中的最大值,但是其实这样与暴力解法完全一样,都是判断“方框”中的最大值并输出,无非是我用了堆排序,快排还能更快呢。。。。这种想法是不可行的。

接着,我进一步的想法是,既然每次只移动一个数字,我只需要将新加入的数字和要弹出的数字进行位置交换,然后从该位置开始调整,将整个堆调整成最大堆,这样就得到了最大的元素,并且效率会更高。这种解法我认为是可行的,但是问题是,如何找到最大堆中要弹出数的位置,这个问题很棘手。因为做题少,我对一些技巧性地东西使用的不是的熟练,甚至一些API都要专门查一查。。。

想到这里我的思路就卡住了,考虑到hard难度还是要尊重一下的,我看了官方题解,基本思路跟我的很像,也是使用了优先级队列,即最大堆,同样是考虑到每次只有一个数的出入,我的想法是将最前边的数弹出,将新加入的数压入,但是这样是完全没有必要的,比如这个例子:
数列:
1 1 1 2 3 5
k=3

前三个数是1 1 1,最大值是1,往后移一位是1 1 2,最大值是2,此时按照我的做法,整个最大堆里边只有1 1 2,但是其实就算第一个1也在最大堆里边,也不会造成影响,不会导致结果出现问题。再往后走, 1 2 3,最大值为3,与1 1 1 2 3的最大值并无不同。

那么什么时候有问题呢?再举一个例子:

5 3 2 1 1 1
比如这个例子中,刚开始是 5 3 2,最大值为5,往后移是3 2 1,最大值是3,这时候就不能让5存在于最大堆中,要把它弹出。

因此我们可以得到这样的结论:当“方框“往后移动时,将新加入的数压入最大堆,假如这时堆顶元素,即最大值是方框之外的元素,将其弹出,直到堆顶为方框内的元素,将其作为结果,而其他非堆顶的非”方框“内元素,不对结果造成任何影响。

在这种想法下就可以解出这道题,然而对于我还有一个问题,对stl十分不熟悉。。。之前做的一道最大堆问题我都是自己写的最大堆,现在最大堆倒是可以写,但是关于判断数的位置一筹莫展,直到看了答案,哦原来可以用pair,实在是妙,可惜我没想起来。。。还是得多熟悉。同时也让我知道了stl中优先级队列确实挺好用的。

源码如下:

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        priority_queue<pair<int,int>> p;
        vector<int> answer;

        for(int i=0;i<k;i++)
        {
            p.emplace(nums[i],i);
        }
        answer.push_back(p.top().first);

        for(int i=k;i<nums.size();i++)
        {
            p.emplace(nums[i],i);
            while(p.top().second<i-k+1)
            {
                p.pop();
            }
            answer.push_back(p.top().first);
        }
        return answer;
    }
};

与题解很相似,没办法,毕竟是看了题解才知道怎么实现的。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值