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 }