Given an array of n integers with duplicate number, and a moving window (size k), move the window at each iteration from the Start of the array, find the maximum number inside the window at each moving.
Has you met this question in a real interview?Yes
Example
For array [1, 2, 7, 7, 8]
, moving window size k = 3
. return[7, 7, 8]
At first the window was at the start of the An array like this
[|1, 2, 7| ,7, 8]
, return the maximum 7
;
Then the window move one step forward.
[1, |2, 7 ,7|, 8]
, return the maximum 7
;
Then the window move one step forward again.
[1, 2, |7, 7, 8|]
, return the maximum 8
;
It is also a question of sliding window. Finding the median, very similar to the find Median from Data stream, can be thought of as a good idea to solve with minheap and maxheap.
However, unlike data flow, sliding window has to be removed, so it is better to use Hashheap.
The specific solution is to break the movement of each window into an increment element and delete the element one at a time. Because there are two of heaps, it is critical to decide which heap to delete. Because test instructions, my practice is that maxheap always store and minheap the same number or more than 1 of the number, so that the median is always the maxheap heap top, each time you can delete the element and the median to compare, large in the minheap, small or equal in Maxheap deleted. The actual solution in the Lintcode timeout, but if more than hashheap write an interface function, contain (now), using the hash table to check, this practice successfully passed, the code is as follows:
classSolution:"""@param nums:a List of integers. @return: The median of element inside the window at each moving. """ defMedianslidingwindow (self, nums, K):ifLen (nums) < Kor notNums:return[] Minheap= Hashheap ('min') Maxheap= Hashheap ('Max') forIinchxrange (k):ifI% 2: Maxheap.add (Nums[i]) Minheap.add (Maxheap.pop ())Else: Minheap.add (Nums[i]) Maxheap.add (Minheap.pop ()) median= [] forIinchxrange (k, Len (nums)): Median.append (Maxheap.top ())ifMinheap.contain (Nums[i-K]): Minheap.delete (Nums[i-K]) Maxheap.add (Nums[i]) Minheap.add (Maxheap.pop () )Else: Maxheap.delete (nums[i-K]) Minheap.add (Nums[i]) Maxheap.add (Minheap.pop ()) Median.append (Maxheap.top ()) returnMedianclassNode (object):"""the type of class stored in the HashMap, in case there is many same heights in the heap, maintain the number """ def __init__(self, id, num): Self.id= ID#ID means its ID in heap arraySelf.num = num#Number of same value in the This ID classHashheap (object):def __init__(self, mode): Self.heap=[] Self.mode=mode self.size=0 Self.hash= {} defTop (self):returnSELF.HEAP[0]ifLen (self.heap) > 0Else0defcontain (self, now):ifSelf.hash.get (now):returnTrueElse: returnFalsedefIsEmpty (self):returnLen (self.heap) = =0def_comparesmall (self, A, b):#compare function in different mode ifA <=B:ifSelf.mode = ='min': returnTrueElse: returnFalseElse: ifSelf.mode = ='min': returnFalseElse: returnTruedef_swap (self, IdA, IdB):#swap the values in the heap, we also need to the changeValA =Self.heap[ida] Valb=Self.heap[idb] NumA=Self.hash[vala].num NumB=Self.hash[valb].num Self.hash[valb]=Node (IdA, NumB) Self.hash[vala]=Node (IdB, NumA) Self.heap[ida], Self.heap[idb]=Self.heap[idb], Self.heap[ida]defAdd (self, now):#the key, height in this placeSelf.size + = 1ifSelf.hash.get (now): Hashnow=Self.hash[now] Self.hash[now]= Node (hashnow.id, Hashnow.num + 1) Else: Self.heap.append (now) Self.hash[now]= Node (len (self.heap)-) Self._siftup (len (self.heap)-1) defPop (self):#pop the top of the heapSelf.size-= 1 Now=Self.heap[0] Hashnow=Self.hash[now] Num=Hashnow.numifnum = = 1: Self._swap (0, Len (self.heap)-1) Self.hash.pop (now) Self.heap.pop () self._siftdown (0)Else: Self.hash[now]= Node (0, Num-1) return NowdefDelete (self, now): Self.size-= 1Hashnow=Self.hash[now] ID=hashnow.id Num=Hashnow.numifnum = = 1: Self._swap (ID, len (self.heap)-1)#Like the common delete operationSelf.hash.pop (now) Self.heap.pop ()ifLen (self.heap) >id:self._siftup (ID) self._siftdown (ID)Else: Self.hash[now]= Node (ID, num-1) defparent (self, id):ifid = =0:return-1return(id-1)/2def_siftup (self,id): whileABS (ID-1)/2 < ID:#Iterative versionParentID = (id-1)/2ifSelf._comparesmall (Self.heap[parentid],self.heap[id]): Break Else: Self._swap (ID, parentid) ID=ParentIDdef_siftdown (self, id):#Iterative version while2*id + 1 <Len (self.heap): l= 2*id + 1R= L + 1Small=IDifSelf._comparesmall (Self.heap[l], Self.heap[id]): Small=LifR < Len (self.heap) andSelf._comparesmall (Self.heap[r], Self.heap[small]): Small=RifSmall! =Id:self._swap (ID, small)Else: BreakID= Small
The time complexity of the above practice is O (NLOGK). But this problem requires a median, and there is no particularly good way to find the solution of O (n) like sliding Window maximum. Just the sauce.
Sliding Window Median