标签:
Given an array of n integer, and a moving window(size k), move the window at each iteration from the start of the array, find the median of the element inside the window at each moving. (If there are even numbers in the array, return the N/2-th number after sorting the element in the window. )
For array [1,2,7,8,5]
, moving window size k = 3. return [2,7,7]
At first the window is at the start of the array like this
[ | 1,2,7 | ,8,5]
, return the median 2
;
then the window move one step forward.
[1, | 2,7,8 | ,5]
, return the median 7
;
then the window move one step forward again.
[1,2, | 7,8,5 | ]
, return the median 7
;
O(nlog(n)) time
Thought:
1) -用List<Integer>() 存sliding window的element.
- 每一个element 找对应的insert position.
- 当i>=k,删除不属于本window的元素
时间开销: remove(Object)需要o(k)的时间;find insert position需要logk的时间。所以总时间开销为n(k+logK). worst case为n^2.
空间开销:o(k)
public ArrayList<Integer> medianSlidingWindow(int[] nums, int k) { // write your code here ArrayList<Integer> res=new ArrayList<Integer>(); if(nums==null||nums.length==0){ return res; } List<Integer> li=new ArrayList<Integer>(); for(int i=0;i<nums.length;i++){ if(i>=k){ li.remove((Integer)(i-k)); } insert(nums,li,i); if(i>=k-1){ res.add(nums[li.get(k%2==0?k/2-1:k/2)]); } } return res; } public void insert(int[] nums,List<Integer> li,int index){ if(li.size()==0){ li.add(index); return; } int left=0; int right=li.size()-1; while(left<=right){ int mid=(left+right)/2; if(nums[index]==nums[li.get(mid)]){ li.add(mid+1,index); return; }else if(nums[index]<nums[li.get(mid)]){ right=mid-1; }else{ left=mid+1; } } li.add(left,index); }
2) 用一个min heap,一个max heap维系。如果k为even,取两个peek的min value,如果k为odd,永远取maxheap的peek.
- maxheap里面的元素为median和之前的元素,且保证peek的值最大。
- minheap存的为median之后的元素,且peek最小。
- 保持maxheap的size>=minheap.size(),避免当k=1,maxheap为null的情况。同时保证k为odd的时候,median永远是maxheap的peek value.
-当i>=k,remove(Object).
时间开销:依然是n(k+logk)...依然没有达到nlogn的要求。
空间开销:o(k)
public ArrayList<Integer> medianSlidingWindow(int[] nums, int k) { ArrayList<Integer> res=new ArrayList<Integer>(); if(nums==null||nums.length==0||k==0){ return res; } PriorityQueue<Integer> minHeap=new PriorityQueue<Integer>(k); PriorityQueue<Integer> maxHeap=new PriorityQueue<Integer>(k,new Comparator<Integer>(){ public int compare(Integer a,Integer b){ return a>b?-1:1; } }); for(int i=0;i<nums.length;i++){ if(i>=k){ if(!minHeap.isEmpty()&&nums[i-k]>=minHeap.peek()){ //time cost: o(K) find the element & logk to remove minHeap.remove(nums[i-k]); }else{ maxHeap.remove(nums[i-k]); } } if(maxHeap.size()==0||nums[i]<maxHeap.peek()){ maxHeap.add(nums[i]); }else{ minHeap.add(nums[i]); } //always make maxheap with greater size. //example : 1,2,7,7,2. when remove 1&add 7. max:7,min:2,7. it‘s wrong!! thus, move one ele to max if(minHeap.size()>maxHeap.size()){ maxHeap.add(minHeap.poll()); }else if(maxHeap.size()>minHeap.size()+1){ minHeap.add(maxHeap.poll()); } if(i>=k-1){ if(minHeap.size()==maxHeap.size()){ res.add(Math.min(maxHeap.peek(),minHeap.peek())); }else{ res.add(maxHeap.peek()); } } } return res; }
LintCode - Sliding Window Median
标签:
原文地址:http://www.cnblogs.com/fifi043/p/4979652.html