Sliding Window Maximum

(原題網址)[http://www.lintcode.com/en/problem/sliding-window-maximum/]

題意:找出window內的最大值

暴力法:會超時

public ArrayList<Integer> maxSlidingWindow(int[] nums, int k) {

    ArrayList<Integer> res = new ArrayList<Integer>();

    if (nums == null || nums.length == 0) {
        return res;
    }

    for (int i = 0; i <= nums.length - k; i++) {
        int max = nums[i];
        for (int j = i; j <= i + k - 1; j++) {
            if (max < nums[j]) {
                max = nums[j];
            }
        }
        res.add(max);
    }

    return res;
}

維護maxheap的方法,也會超時,除非加入hashheap來幫助加速刪除的動作

public ArrayList<Integer> maxSlidingWindow(int[] nums, int k) {

    ArrayList<Integer> res = new ArrayList<Integer>();

    if (nums == null || nums.length == 0) {
        return res;
    }

    PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(1, Collections.reverseOrder());

    for (int i = 0; i < nums.length; i++) {
        maxHeap.offer(nums[i]);

        if (i >= k - 1) {
            res.add(maxHeap.peek());

            int toBeDelete = nums[i - k + 1];
            maxHeap.remove(toBeDelete);
        }
    }

    return res;
}

用deque(雙向隊列)來解

public ArrayList<Integer> maxSlidingWindow(int[] nums, int k) {

    ArrayList<Integer> res = new ArrayList<Integer>();

    if (nums == null || nums.length == 0) {
        return res;
    }

    // deque 要用arraydeque來實作
    Deque<Integer> deque = new ArrayDeque<Integer>();

    for (int i = 0; i < nums.length; i++) {

        // 把比目前這個數都小的其他數都從後面poll掉,
        // 因為那些數不可能再成為maximum的其中一員
        while(!deque.isEmpty() && nums[i] >deque.peekLast()) {
            deque.pollLast();
        }

        // 把目前最大的poll進來,此時deque可能還有數,但一定比目前這個數大
        deque.offer(nums[i]);

        // 確保超出window範圍的數已被刪除
        if (i > k - 1) {
            if (deque.peekFirst() == nums[i - k]) {
                deque.pollFirst();
            }
        }

        // 此時可以放心把deque的最前面那個peek出來放到答案中
        if (i >= k - 1) {
            res.add(deque.peekFirst());
        }
    }

    return res;
}

[Updated on 2019.10.01]

解法:

我們可以使用一個Monotonic Queue來實現,最大元素的index在queue的peek,最小的元素的index在queue的tail,deque中放的是index而非數值。

class Solution {
    public int[] maxSlidingWindow(int[] a, int k) {        

        if (a == null || k <= 0) {
            return new int[0];
        }

        int length = a.length;
        int[] result = new int[length - k + 1];
        int pos = 0;

        // store index
        Deque<Integer> deque = new ArrayDeque<>();
        for (int i = 0; i < length; i++) {

            // remove numbers out of range k
            while (!deque.isEmpty() && deque.peek() < (i - k + 1)) {
                deque.poll();
            }

            // remove smaller numbers in k range as they are useless
            while (!deque.isEmpty() && a[deque.peekLast()] < a[i]) {
                deque.pollLast();
            }

            // deque contains index... result contains content
            deque.offer(i);
            if (i >= k - 1) {
                result[pos++] = a[deque.peek()];
            }
        }
        return result;
    }
}
Reference:

results matching ""

    No results matching ""