您的位置:首页 > 其它

239. Sliding Window Maximum

2016-06-28 22:25 169 查看
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.

For example,

Given nums = 
[1,3,-1,-3,5,3,6,7]
, and k =
3.
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


Therefore, return the max sliding window as 
[3,3,5,5,6,7]
.

Note: 

You may assume k is always valid, ie: 1 ≤ k ≤ input array's size for non-empty array.

Follow up:

Could you solve it in linear time?

Hint:
How about using a data structure such as deque (double-ended queue)?
The queue size need not be the same as the window’s size.
Remove redundant elements and the queue should store only elements that need to be considered.

   使用有序的Treemap将元素值和其次数做映射,扫描移动,每小段的max值即为Treemap中的lastkey。
时间复杂度O(NlogN)

public static int[] maxSlidingWindow(int[] nums, int k)
{
int len=nums.length;
if(len<1)
return new int[]{};

TreeMap<Integer, Integer> treemap=new TreeMap<>();
int cnt=0;
int[] retarr=new int[len-k+1];

for(int i=0;i<k;i++)
if(!treemap.containsKey(nums[i]))
treemap.put(nums[i], 1);
else {
treemap.put(nums[i], treemap.get(nums[i])+1);
}
retarr[cnt++]=treemap.lastKey();

for(int i=1;i<=len-k;i++)
{
int removeele=nums[i-1];
int times=treemap.get(removeele);
if(times==1)
treemap.remove(removeele);
else {
treemap.put(removeele,times-1);
}

if(!treemap.containsKey(nums[i+k-1]))
treemap.put(nums[i+k-1], 1);
else {
treemap.put(nums[i+k-1], treemap.get(nums[i+k-1])+1);
}

retarr[cnt++]=treemap.lastKey();
}

return retarr;
}


-------------------------------------------------------------------------------------------
另外好的方法,摘自 https://leetcode.com/discuss/46578/java-o-n-solution-using-deque-with-explanation


Java O(n) solution using deque with explanation

We scan the array from 0 to n-1, keep "promising" elements in the deque. The algorithm is amortized O(n) as each element is put and polled once.

At each i, we keep "promising" elements, which are potentially max number in window [i-(k-1),i] or any subsequent window. This means

If an element in the deque and it is out of i-(k-1), we discard them. We just need to poll from the head, as we are using a deque and elements are ordered as the sequence in the array

Now only those elements within [i-(k-1),i] are in the deque. We then discard elements smaller than a[i] from the tail. This is because if a[x] <a[i] and x<i, then a[x] has no chance to be the "max" in [i-(k-1),i],
or any other subsequent window: a[i] would always be a better candidate.

As a result elements in the deque are ordered in both sequence in array and their value. At each step the head of the deque is the max element in [i-(k-1),i]

public int[] maxSlidingWindow(int[] a, int k) {
if (a == null || k <= 0) {
return new int[0];
}
int n = a.length;
int[] ret = new int[n-k+1];
int cnt = 0;
// store index
ArrayDeque<Integer> q = new ArrayDeque<>();
for (int i = 0; i < a.length; i++) {
// remove numbers out of range k
while (!q.isEmpty() && q.peek() < i - k + 1) {
q.poll();
}
// remove smaller numbers in k range as they are useless
while (!q.isEmpty() && a[q.peekLast()] < a[i]) {
q.pollLast();
}
// q contains index... r contains content
q.offer(i);
if (i >= k - 1) {
ret[cnt++] = a[q.peek()];
}
}
return ret;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: