數據結構與算法隨筆之優先隊列-求滑動窗口最大值(三)

這篇文章咱們來看一道題目求滑動窗口最大值問題(在leetcode上的地址:滑動窗口最大值)java

題目描述

給定一個長度爲N的數組 nums,有一個大小爲 k 的滑動窗口從數組的最左側移動到數組的最右側。你只能夠看到在滑動窗口 k 內的數字。滑動窗口每次只向右移動一位。返回滑動窗口最大值。數組

示例:ide

輸入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3
輸出: [3,3,5,5,6,7]

解決方案

1、使用最大堆來實現code

首先定義一個大小爲K的最大堆,把窗口裏面的數據入堆,這樣堆頂的數據就是最大值,當窗口向右移動的時候,咱們還須要作的一件事情就是把不在窗口的數據移出堆,把進入窗口的數據放入堆,此時堆也會作相應調整,維持最大值在堆頂。代碼以下:隊列

public class SlidingWindow {
    public int[] maxSlidingWindow(int[] nums, int k) {
        if(nums == null || nums.length == 0 || k < 1 || k > nums.length) {
            return null;
        }
        if(k == 1) {
            return nums;
        }
        int[] result = new int[nums.length - k + 1];
        int j = 0;
        //用優先隊列構建最大堆
        PriorityQueue<Integer> queue = new PriorityQueue<>(k, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                if(o1.compareTo(o2) == 0) {
                    return 0;
                }else if(o1.compareTo(o2) > 0) {
                    return -1;
                }else {
                    return 1;
                }
            }
        });
        for(int i=0;i<nums.length;i++) {
            //把不在窗口的數據移除掉
            if(i-k+1 > 0) {
                queue.remove(nums[i-k]);
            }
            //把移進窗口的數據加入最大堆,最大值必定會在堆頂
            queue.add(nums[i]);
            if(i-k+1 < 0) {
                continue;
            }
            result[j++] = queue.peek();
        }
        return result;
    }
}

複雜度分析leetcode

  • 時間複雜度:O(nlogk)

2、使用雙端隊列來實現rem

定義一個大小爲K的雙端隊列,把窗口裏的數據放入隊列,每次入隊的時候進行判斷,隊列裏面小於入隊數據時,須要出隊,必定保持最大值在隊列的最左端,代碼實現以下:get

public class SlidingWindow {
    public int[] maxSlidingWindow(int[] nums, int k) {
        if(nums == null || nums.length == 0 || k < 1 || k > nums.length) {
            return null;
        }
        if(k == 1) {
            return nums;
        }
        int[] result = new int[nums.length - k + 1];
        int m = 0;
        ArrayDeque<Integer> queue = new ArrayDeque<>(k);
        for(int i=0;i<nums.length;i++) {
            //把不在窗口的數據移除掉
            while(!queue.isEmpty() && queue.peek() < i-k+1) {
                queue.remove();
            }
            //比較大小,把較小的數據移除掉,保證最大值在隊列的最左端
            while(!queue.isEmpty() && nums[queue.peekLast()] <= nums[i]) {
                queue.removeLast();
            }
            queue.add(i);
            if(i-k+1 < 0) {
                continue;
            }
            result[m++] = nums[queue.peek()];
        }
        return result;
    }
}

複雜度分析it

  • 時間複雜度:O(n)
相關文章
相關標籤/搜索