zoukankan      html  css  js  c++  java
  • 剑指Offer——滑动窗口的最大值

    Question

    给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}; 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。

    解法1. 遍历

    • 依次遍历原数组的三个元素,找出最大值,时间复杂度为O(n * k).
    class Solution {
    public:
        vector<int> maxInWindows(const vector<int>& num, unsigned int size)
        {
            vector<int> res;
            if (size <= 0)
                return res;
            for (int i = 0; i < num.size() - size + 1; i++) {
    			int maxNum = INT_MIN;
                for (int j = 0; j < size; j++) {
                    if (num[i + j] > maxNum)
                        maxNum = num[i + j];
                }
                res.push_back(maxNum);
            }
            return res;
        }
    }
    

    解法2. 最大优先队列

    • 优先队列中的每个元素都是pair,前面存储值,后面存储坐标,因为是最大优先队列,那么会根据第一个值从大到小排序,如果队列中最大值已经失效,那么就出队列。调整一次优先最烈的时间复杂度为O(lg(size)),所以总的时间复杂度为O(nlg(size)).
        vector<int> maxInWindows(const vector<int>& num, unsigned int size) {
            if (size <= 0 || num.size() < size)
                return vector<int>();
            
            typedef pair<int, int> Pair;
            priority_queue<Pair> Q;
            for (int i = 0; i < size; i++) {
                Q.push(Pair(num[i], i));
            }
            
            vector<int> res;
            for (int i = size; i < num.size(); i++) {
                res.push_back(Q.top().first);
                
                // 判断最大值是否失效
                while (!Q.empty() && Q.top().second <= i - size)
                    Q.pop();
                Q.push(Pair(num[i], i));
            }
            
            res.push_back(Q.top().first);
            
            return res;
        }
    

    解法3. 用一个双端队列

    • 做法和解法2类似,但是不同的地方在于,如果有一个新的比队列中的值都大的话,那么就先清空队列。 具体做法的话就是,从队尾判断是否队列的值比当前值小,如果小就出队列,因为小的话是不可能成为最大值的。 最队首去判断最大值是否已经失效。
      整体时间复杂度为O(n).
        vector<int> maxInWindows(const vector<int>& num, unsigned int size) {
            if (size <= 0 || num.size() < size)
                return vector<int>();
            
            deque<int> dq;
            for (int i = 0; i < size; i++) {
                while (!dq.empty() && num[i] > num[dq.back()])
                    dq.pop_back();
                // 存的是最大值的坐标
                dq.push_back(i);
            }
            
            vector<int> res(num.size() - size + 1);
            for (int i = size; i < num.size(); i++) {
                res[i - size] = num[dq.front()];
                
                // 尾部判断是否应该出队列
                while (!dq.empty() && num[i] > num[dq.back()])
                    dq.pop_back();
                // 前部判断是否最大值已经失效
                while (!dq.empty() && dq.front() <= i - size)
                    dq.pop_front();
                
                dq.push_back(i);
            }
            res[num.size() - size] = num[dq.front()];
            return res;
        }
    
  • 相关阅读:
    LeetCode Merge Two Sorted Lists 归并排序
    LeetCode Add Binary 两个二进制数相加
    LeetCode Climbing Stairs 爬楼梯
    034 Search for a Range 搜索范围
    033 Search in Rotated Sorted Array 搜索旋转排序数组
    032 Longest Valid Parentheses 最长有效括号
    031 Next Permutation 下一个排列
    030 Substring with Concatenation of All Words 与所有单词相关联的字串
    029 Divide Two Integers 两数相除
    028 Implement strStr() 实现 strStr()
  • 原文地址:https://www.cnblogs.com/zhonghuasong/p/7089672.html
Copyright © 2011-2022 走看看