滑動(dòng)窗口的最大值&隊(duì)列的最大值

滑動(dòng)窗口的最大值

給定一個(gè)數(shù)組 nums遏佣,有一個(gè)大小為 k的滑動(dòng)窗口從數(shù)組的最左側(cè)移動(dòng)到數(shù)組的最右側(cè)机蔗。你只可以看到在滑動(dòng)窗口內(nèi)的 k 個(gè)數(shù)字植袍×爬悖滑動(dòng)窗口每次只向右移動(dòng)一位岸裙。

返回滑動(dòng)窗口中的最大值建芙。

示例:

輸入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3
輸出: [3,3,5,5,6,7]
解釋:
滑動(dòng)窗口的位置 最大值


[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

方法一:暴力
每次都在滑動(dòng)窗口中計(jì)算最大值

public int[] maxSlidingWindow(int[] nums, int k) {
    int[] ans=new int[nums.length-k+1];
    for (int i = 0; i <= nums.length-k; i++) {
        int max=Integer.MIN_VALUE;
        for (int j = i; j < i+k; j++) {
            if(nums[j]>max){
                max=nums[j];
            }
        }
        ans[i]=max;
    }
    return ans;
}

時(shí)間復(fù)雜度O(nk),空間復(fù)雜度O(n-k+1)

方法二:利用堆
將在滑動(dòng)窗口中的元素放入堆中砚作,堆頂為最大值

public int[] maxSlidingWindow(int[] nums, int k) {
    if(k==0){
        return new int[0];
    }
    int[] ans=new int[nums.length-k+1];
    PriorityQueue<Integer> queue=new PriorityQueue<>((o1,o2)->o2-o1);
    for(int i=0;i<k-1;i++){
        queue.offer(nums[i]);
    }
    for(int i=0;i<nums.length-k+1;i++){
        queue.offer(nums[i+k-1]);
        ans[i]=queue.peek();
        queue.remove(nums[i]);//移除滑動(dòng)窗口之外的元素
    }
    return ans;
}

時(shí)間復(fù)雜度O(nlogk)

方法三:雙向隊(duì)列
隊(duì)列中的元素都在滑動(dòng)窗口中窘奏,遞減(可以重復(fù))
在遍歷過程中:

  • 將不在窗口的元素從隊(duì)列中移除
  • 將隊(duì)列中比當(dāng)前元素小的移除
  • 將當(dāng)前元素添加到隊(duì)列中
  • 隊(duì)首元素就是當(dāng)前的最大值
public int[] maxSlidingWindow(int[] nums, int k) {
    int[] ans = new int[nums.length - k + 1];
    Deque<Integer> deque = new LinkedList<>();
    for (int i = 0; i < k; i++) {
        clean(deque, nums[i], nums, i, k);
    }
    ans[0] = deque.getFirst();
    for (int i = k; i < nums.length; i++) {
        clean(deque, nums[i], nums, i, k);
        ans[i - k + 1] = deque.getFirst();
    }
    return ans;
}

public void clean(Deque<Integer> deque, int num, int[] nums, int cur, int k) {
    if (cur - k >= 0 && deque.getFirst() == nums[cur - k]) {//移除滑動(dòng)窗口之外的元素
        deque.pollFirst();
    }
    while (!deque.isEmpty() && num>deque.getLast() ) {//移除比當(dāng)前更小的元素
        deque.pollLast();
    }
    deque.addLast(num);
}

時(shí)間復(fù)雜度O(n)

新版本:
隊(duì)首:小元素 隊(duì)尾:大元素

public int[] maxSlidingWindow(int[] nums, int k) {
    if (k == 0) {
        return new int[0];
    }
    int[] ans = new int[nums.length - k + 1];
    Deque<Integer> deque = new LinkedList<>();
    for (int i = 0; i < k - 1; i++) {
        removeSmaller(deque, nums[i]);
        deque.addFirst(nums[i]);
    }
    for (int i = 0; i < ans.length; i++) {
        int index = i + k - 1;
        removeSmaller(deque, nums[index]);
        deque.addFirst(nums[index]);
        removeOutQueue(deque, nums, k, index);
        ans[i] = deque.peekLast();
    }
    return ans;
}

public void removeSmaller(Deque<Integer> deque, int num) {
    while (!deque.isEmpty() && deque.getFirst() < num) {
        deque.pollFirst();
    }
}

public void removeOutQueue(Deque<Integer> deque, int[] nums, int k, int cur) {
    if (cur - k >= 0 && nums[cur - k] == deque.getLast()) {
        deque.pollLast();
    }
}

隊(duì)列的最大值

請(qǐng)定義一個(gè)隊(duì)列并實(shí)現(xiàn)函數(shù) max_value 得到隊(duì)列里的最大值,要求函數(shù)max_value葫录、push_backpop_front均攤時(shí)間復(fù)雜度都是O(1)着裹。

若隊(duì)列為空,pop_frontmax_value 需要返回 -1

示例 1:

輸入:
["MaxQueue","push_back","push_back","max_value","pop_front","max_value"]
[[],[1],[2],[],[],[]]
輸出:[null,null,null,2,1,2]

示例 2:

輸入:
["MaxQueue","pop_front","max_value"]
[[],[],[]]
輸出:[null,-1,-1]

限制

  • 1 <= push_back,pop_front,max_value的總操作數(shù) <= 10000
  • 1 <= value <= 10^5

使用輔助雙端隊(duì)列米同,隊(duì)首存當(dāng)前的最大值骇扇,整個(gè)隊(duì)列遞減

  • push(v):從隊(duì)尾移除所有小于當(dāng)前的元素x(在移除v之前,必須移除了x面粮,而在移除v之前少孝,最大值不可能是x),再將當(dāng)前元素添加到隊(duì)尾
  • pop():如果隊(duì)首元素等于移除的元素熬苍,則移除隊(duì)首元素
class MaxQueue {

    private Queue<Integer> queue = new LinkedList<>();

    private Deque<Integer> maxQueue = new LinkedList<>();

    public int max_value() {
        if (maxQueue.isEmpty()) {
            return -1;
        }
        return maxQueue.getFirst();
    }

    public void push_back(int value) {
        queue.offer(value);
        while (!maxQueue.isEmpty() && value > maxQueue.getLast()) {
            maxQueue.pollLast();
        }
        maxQueue.offerLast(value);
    }

    public int pop_front() {
        if (queue.isEmpty()) {
            return -1;
        }
        int value = queue.poll();
        if (maxQueue.getFirst() == value) {
            maxQueue.pollFirst();
        }
        return value;
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末稍走,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子柴底,更是在濱河造成了極大的恐慌钱磅,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,590評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件似枕,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡年柠,警方通過查閱死者的電腦和手機(jī)凿歼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門褪迟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人答憔,你說我怎么就攤上這事味赃。” “怎么了虐拓?”我有些...
    開封第一講書人閱讀 169,301評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵心俗,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我蓉驹,道長(zhǎng)城榛,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,078評(píng)論 1 300
  • 正文 為了忘掉前任态兴,我火速辦了婚禮狠持,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘瞻润。我一直安慰自己喘垂,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,082評(píng)論 6 398
  • 文/花漫 我一把揭開白布绍撞。 她就那樣靜靜地躺著正勒,像睡著了一般。 火紅的嫁衣襯著肌膚如雪傻铣。 梳的紋絲不亂的頭發(fā)上章贞,一...
    開封第一講書人閱讀 52,682評(píng)論 1 312
  • 那天,我揣著相機(jī)與錄音矾柜,去河邊找鬼阱驾。 笑死,一個(gè)胖子當(dāng)著我的面吹牛怪蔑,可吹牛的內(nèi)容都是我干的里覆。 我是一名探鬼主播,決...
    沈念sama閱讀 41,155評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼缆瓣,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼喧枷!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起弓坞,我...
    開封第一講書人閱讀 40,098評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤隧甚,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后渡冻,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體戚扳,經(jīng)...
    沈念sama閱讀 46,638評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,701評(píng)論 3 342
  • 正文 我和宋清朗相戀三年族吻,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了帽借。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片珠增。...
    茶點(diǎn)故事閱讀 40,852評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖砍艾,靈堂內(nèi)的尸體忽然破棺而出蒂教,到底是詐尸還是另有隱情,我是刑警寧澤脆荷,帶...
    沈念sama閱讀 36,520評(píng)論 5 351
  • 正文 年R本政府宣布凝垛,位于F島的核電站,受9級(jí)特大地震影響蜓谋,放射性物質(zhì)發(fā)生泄漏梦皮。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,181評(píng)論 3 335
  • 文/蒙蒙 一孤澎、第九天 我趴在偏房一處隱蔽的房頂上張望届氢。 院中可真熱鬧,春花似錦覆旭、人聲如沸退子。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽寂祥。三九已至,卻和暖如春七兜,著一層夾襖步出監(jiān)牢的瞬間丸凭,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評(píng)論 1 274
  • 我被黑心中介騙來泰國(guó)打工腕铸, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留惜犀,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,279評(píng)論 3 379
  • 正文 我出身青樓狠裹,卻偏偏與公主長(zhǎng)得像虽界,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子涛菠,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,851評(píng)論 2 361