题目:
给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{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]}。
思路:
-
常规方法:遍历,从左到右,每次局部再统计最大值,将最大值加入到结果list中,假设num[]数组的长度是m,size大小是n的话,时间复杂度就是O(mn)
-
利用大根堆,首先创建大根堆heap,大根堆的容量就是size,先加size个数加入到heap中,并将heap堆顶加入到结果list中。然后堆heap删除掉之前第一个进堆的数,后面的数再进堆,将此时堆顶元素加入到list中,循环此步骤。时间复杂度为O(mlogn)
Java
package nowcoder;
import java.util.ArrayList;
public class S64_MaxInWindows {
public ArrayList<Integer> maxInWindows(int[] num, int size){
ArrayList<Integer> list = new ArrayList<Integer>();
if (size <= 0)
return list;
int length = num.length;
for (int i=0;i<length - size+1;i++){
int j=i;
int max = 0;
while (j < i+size){
if (num[j] > max)
max = num[j];
j++;
}
list.add(max);
}
return list;
}
public static void main(String[] args){
S64_MaxInWindows s64 = new S64_MaxInWindows();
int[] num = {10,14,12,11};
System.out.println(s64.maxInWindows(num, 0));
}
}
Java,利用堆
package nowcoder;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.PriorityQueue;
public class S64_MaxInWindows_new {
public ArrayList<Integer> maxInWindows(int[] num, int size){
//创建大根堆
PriorityQueue<Integer> heap = new PriorityQueue<Integer>(size, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
ArrayList<Integer> list = new ArrayList<Integer>();
if (size <= 0)
return list;
int length = num.length;
for (int i=0;i<size;i++){
heap.offer(num[i]);
}
list.add(heap.peek());
for (int i=1;i<length-size+1;i++){
heap.remove(num[i-1]);
heap.offer(num[i+size-1]);
list.add(heap.peek());
}
return list;
}
public static void main(String[] args){
S64_MaxInWindows_new s64 = new S64_MaxInWindows_new();
int[] num = {2,3,4,2,6,2,5,1};
System.out.println(s64.maxInWindows(num, 3));
}
}
Python 利用双端队列
class MaxInWindows:
def maxInWindows(self, num, size):
queue, res, i = [], [], 0
while size > 0 and i < len(num):
if len(queue) > 0 and i-size+1 > queue[0]: #若最大值queue[0]位置过期 则弹出
queue.pop(0)
while len(queue) > 0 and num[queue[-1]] < num[i]: #每次弹出所有比num[i]小的数字
queue.pop()
queue.append(i)
if i >= size-1:
res.append(num[queue[0]])
i += 1
return res
if __name__ == '__main__':
test = MaxInWindows()
num = [2, 3, 4, 2, 6, 2, 5, 1]
print(test.maxInWindows(num, 3))