【剑指offer】59、队列的最大值(不熟)

题目一

给定一个数组和滑动窗口的大小,请找出所有滑动窗口里的最大值。例如,{2,3,4,2,6,2,5,1}以及窗口大小3,那么存在6个滑动窗口,最大值分别为{4,4,6,6,6,5}  滑动

思路

滑动窗口可以看作是队列,为了得到滑动窗口的最大值,队列可以从两端删除元素,因此使用双向队列。

原则:对于新来的元素k,将其与队列中元素比较,

1、若队列中有元素比k小,直接将之前比k小的元素移除队列(因为不可能再成为后面滑动窗口的最大值),压入k

2、若队列中元素x比k大,则根据下标检测x是否在窗口内,如果不在则移除队列,压入k

队列的第一个元素是滑动窗口的最大值,同时要存储数字在数组的下标,而不是数值,用来判断滑动窗口是否包含数字

举例说明:

1、将2压入队列

2、3比2大,弹出2,压入3

3、4比3大,弹出3,压入4

4、2比4小,4还在窗口内,保留4,压入2

5、6比4和2都大,因此弹出4和2,压入6

6、2比6小,6在窗口内,保留6,压入2

7、5比2大,比6小,且6还在窗口内,弹出2,压入5

8、1比6和5都小,但是6不在窗口内,6弹出,压入1

class Solution {
public:
    vector<int> maxInWindows(const vector<int>& num, unsigned int size)
    {
        vector<int> max_in_win;
        if (num.size() >= size && size >= 1)
        {
            deque<int> index; // 存的是索引
            
            for (unsigned int i = 0; i < size; i++) // 先把size-1个元素压入队列,此时还不构成窗口
            {
                while ( !index.empty() && num[i] >= num[index.back()])
                    index.pop_back();
                index.push_back(i);
            }
            
            for (unsigned int i = size; i < num.size(); i++)
            {
                max_in_win.push_back(num[index.front()]);
                // 新来元素比某些元素大,则比新元素小的全删除
                while (!index.empty() && num[i] >= num[index.back()]) 
                    index.pop_back();
                // 对头元素的下标不在窗口内了,则弹出
                if(!index.empty() && index.front() <= (int)(i - size))
                    index.pop_front();
                index.push_back(i);
            }
            
            max_in_win.push_back(num[index.front()]);
        }
        return max_in_win;
    }
};

题目二

请定义一个队列并实现函数max得到队列里的最大值,要求函数max,push_back,pop_front的时间复杂度都是O(1)

思路

滑动窗口可以看作队列,因此定义两个队列data和maximum

 

 

猜你喜欢

转载自www.cnblogs.com/shiganquan/p/9351007.html