算法學習之隊列的最大值

題目一:滑動窗口的最大值。

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

思路:我們模擬一個左右開口長度固定的滑動小車(窗口),使用LinkList只保存最大值索引(因爲LinkList方便去頭去尾)

1、確定小車初始位置在起點

2、掛擋起車,開始滑動,同時根據條件剔除車裏年齡已經不是最大的人(即上一個最大值),同時剔除要下車的人(即索引不在當前區間內的值)

3、添加終點遺漏的人(即最後一個區間的最大值)

import java.util.*;
public class Solution {
    public ArrayList<Integer> maxInWindows(int [] num, int size)
    {
        ArrayList<Integer> result = new ArrayList<>();
        if(num==null||num.length<=0||num.length<size||size<1)return result;
       
        LinkedList<Integer> list  = new LinkedList<>();
        // 首先確定第一段的最大值0~size間的最大值
        for(int i = 0 ;i<size;i++){
            if(!list.isEmpty()&&num[i]>=num[list.getLast()]){
                list.removeLast();
            }
            list.add(i);
        }
        // 在存值並開始求size之後的
        for(int i = size;i<num.length;i++){
            result.add(num[list.getFirst()]);// 存儲上一次區間中獲取到的最大值
            // 同上,添加前判斷如果將要加入的值比原來的值大則刪除上一個存儲的最大值
            // 前可能存在兩個以上,所以循環剔除
            while(!list.isEmpty()&&num[i]>=num[list.getLast()]){ 
                list.removeLast();
            }
            // 同時刪除頭部已經離開區間的最大值
            if(!list.isEmpty()&&i-list.getFirst()>=size){ //index值應該比size小1,因爲從起始點爲0,size起始點爲1
                list.removeFirst();
            }
            list.add(i);
        }
        // 因爲窗口移動到末端前一位循環就結束了,並且不能強制length+1,因爲是引發下標越界。所有在循環外手動添加最後一位
        result.add(num[list.getFirst()]);
        return result;
    }
}

時間複雜度:O(n)

空間複雜度:O(k) k爲size大小

練習地址:https://www.nowcoder.com/practice/1624bc35a45c42c0bc17d17fa0cba788

題目二:隊列的最大值

請定義一個隊列並實現函數max得到隊列裏的最大值,要求函數max、push和pop的時間複雜度都是O(1)。

思路:其實沒啥好說的這題。。。emmm。使用雙鏈表記錄不同的值就可以了


    LinkedList<TemData> maxs = new LinkedList<>();
    LinkedList<TemData> data = new LinkedList<>();
    int index = 0;

    public void push(int number) {
        while (!maxs.isEmpty() && number >= maxs.getLast().num) {
            maxs.removeLast();
        }
        TemData temData = new TemData(number, index++);
        maxs.add(temData);
        data.add(temData);

    }

    public int pop() throws Exception {
        if (maxs.isEmpty()) {
            throw new Exception("queue is empty");
        }
        if (maxs.getFirst().index == data.getFirst().index) { // index存在的意義就是對標兩個link
            maxs.removeFirst();
        }
        return data.removeFirst().num;
    }

    public int max() throws Exception {
        if(maxs.isEmpty()) {
            throw new Exception("queue is empty");
        }
        return maxs.getFirst().num;
    }

    class TemData {
        int index;
        int num;

        public TemData(int index, int num) {
            this.index = index;
            this.num = num;
        }
    }

時間複雜度:O(1)

空間複雜度:O(1)

發佈了94 篇原創文章 · 獲贊 8 · 訪問量 5139
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章