leetcode239.滑动窗口最大值(困难,单调队列)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
思路:单调队列
具体思路: 维护一个从队头到队尾单调递减的队列。
优化: 队列直接存下标,就不存元素值了。

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        
        int n = nums.size();
        deque<int> dq;  
        vector<int> ans;
        for (int i = 0; i < k; ++i) {
            while (!dq.empty() && nums[dq.back()] < nums[i]) dq.pop_back();
            dq.push_back(i);
        }
        if (dp.size()) ans.push_back(nums[dq.front()]); //加判断
        for (int i = k; i < n; ++i) {
            while (!dq.empty() && nums[dq.back()] < nums[i]) dq.pop_back();
            dq.push_back(i);
            while (dq.front() < i - k + 1) dq.pop_front();
            ans.push_back(nums[dq.front()]);
        }
        return ans;
    }
};

代码:用front() 和back()
易错点:考虑数组为空的情况。

思路二:优先队列 O(nlogn) 复杂度高
难点: 从堆中删除指定元素(窗口滑动后左边的元素)不可能实现,怎么处理?
解决方案 那就不删除呗,每次得到最大元素的时候,判断堆顶元素是否在滑动窗口中,如果不在一直删除堆顶元素直到堆顶元素是滑动窗口内的元素
难点: 那么怎么判断栈顶元素是否属于窗口内元素这个集合呢?
解决方案: 堆中元素的类型为pair<int, int>,first存nums[index],second存index,每次对堆顶元素的second与窗口的左边界进行对比

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
         
        int n = nums.size();
        priority_queue<pair<int, int>> pq;
        vector<int> ans;
        for (int i = 0; i < k; ++i) {
            pq.push({nums[i], i});
        }
        ans.push_back(pq.top().first);
        for (int i = k; i < n; ++i) {
            pq.push({nums[i], i});
            while (pq.top().second < i - k + 1) pq.pop();
            ans.push_back(pq.top().first);
        }
        return ans;
    }
};

思路三:set O(nlogk) 复杂度较高
注意: 数组中可能会存在重复元素,所以不能用set,改成multiset

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
         
        int n = nums.size();
        multiset<int, greater<int>> st;
        vector<int> ans;
        for (int i = 0; i < k; ++i) {
            st.insert(nums[i]);
        }
        if (st.size()) ans.push_back(*st.begin());
        for (int i = k; i < n; ++i) {
            st.erase(st.find(nums[i - k]));
            st.insert(nums[i]);
            ans.push_back(*st.begin());
        }
        return ans;
    }
};

易错点
multiset 可能有重复元素,删除一个元素时会都删掉:mst.erase(st.find(nums[i - k]));

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值