[leetcode]239. Sliding Window Maximum滑動窗口最大值
Given an array nums, there is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves right by one position. Return the max sliding window.
Example:
Input: nums = [1,3,-1,-3,5,3,6,7], and k = 3 Output: [3,3,5,5,6,7] Explanation: Window position Max --------------- ----- [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
題意:
給定一個長度為k的滑動窗口不斷從左往右滑動,給出過程中的各個最大值。
思路:
使用一個每次能取出極值的數據結構,TreeMap,如下圖,其底層用BST來儲存
TreeMap要求key必須是比較大小(自然排序或定制排序)
以[1,1,-1,-3,5,3,6,7], k = 3 為例, 遍歷數組,將數組每個元素作為TreeMap的key, 將該元素出現頻率作為對應value
[1, 1, -1, -3, 5, 3, 6, 7]
^ i = 0
[1, 1, -1, -3, 5, 3, 6, 7]
^ i = 1
[1, 1, -1, -3, 5, 3, 6, 7]
^ i = 2
[1, 1, -1, -3, 5, 3, 6, 7]
^ i = 3 此時 i >= k 則先將a[i-k]在TreeMap中對應的出現頻率(value) 減1
再check一下 a[i-k]對應的value是否為0,為0則直接刪去。
此例中,a[i-k] = 1, 在TreeMap中對應的value為2,那麽value減1 後為1, 仍然繼續保留。
由此可以看出,大體思路是用TreeMap維護一個所有value值相加為K的BST
用lastKey()來取出當前TreeMap裏最大值(根據BST性質,最大值一定在最右)
代碼:
1 class Solution { 2 public int[] maxSlidingWindow(int[] a, int k) { 3 // corner case 4 if(k <= 0) return new int[]{}; 5 //TreeMap要求其key必須可比較大小 6 TreeMap<Integer, Integer> map = new TreeMap<>((o1,o2) -> o1 - o2); 7 int[] result = new int[a.length - k + 1]; 8 9 for(int i = 0; i < a.length; i++){ 10 // 1. add to bst 11 if(map.containsKey(a[i])){ 12 map.put(a[i], map.get(a[i]) + 1 ); 13 }else{ 14 map.put(a[i], 1); 15 } 16 // 2. remove from bst when window sliding 17 if( i >= k){ 18 map.put(a[i - k] , map.get(a[i - k]) - 1 ); 19 if(map.get(a[i - k]) == 0 ){ 20 map.remove(a[i - k]); 21 } 22 } 23 // 3. get max 24 if( i + 1 >= k){ 25 result[ i - (k - 1)] = map.lastKey(); 26 } 27 } 28 return result; 29 }
[leetcode]239. Sliding Window Maximum滑動窗口最大值