1. 程式人生 > >【劍指offer】59、隊列的最大值(不熟)

【劍指offer】59、隊列的最大值(不熟)

最大值 ber 元素 const 所有 刪除元素 windows 窗口 push_back

題目一

給定一個數組和滑動窗口的大小,請找出所有滑動窗口裏的最大值。例如,{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

【劍指offer】59、隊列的最大值(不熟)