赞
踩
双向队列
思考一下:对于数组nums
,我们想知道max(nums[i-k],...,nums[i])
如何高效处理?
单调队列
单调队列,即从队首到队尾单调的队列。
假设nums = [10,8,6,4,5,12],k=2
,单调队列滑动窗口入队出队过程:
需要注意的是在滑动窗口时,我们需要知道原数据节点的下标,所以需要以二元组绑定索引值的形式处理。这种情况下,队首始终是最大值,并满足从队首到队尾单调递减。
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
int n = nums.length;
int[] ans = new int[n-k+1];
Deque<Integer[]> ql = new ArrayDeque<Integer[]>();
for (int i = 0; i < n; i++) {
while (!ql.isEmpty() && i-ql.peekFirst()[0] >= k) ql.pollFirst();
Integer[] t = {i, nums[i]};
while (!ql.isEmpty() && ql.peekLast()[1] < nums[i]) ql.pollLast();
ql.offerLast(t);
if (i-k+1 >= 0) ans[i-k+1] = ql.peekFirst()[1];
}
return ans;
}
}
Go语言手写数据结构
// 链表节点 type Node struct { Idx int Val int Left *Node Right *Node } // 双向链表 type Deque struct { First *Node Last *Node } // 判断队空 func (this Deque) IsEmpty() bool { return this.First == nil } // 队首值 func (this Deque) getFirst() int { return this.First.Val } // 队尾值 func (this Deque) getLast() int { return this.Last.Val } // 队首下标 func (this Deque) FirstIndex() int { return this.First.Idx } // 队尾下标 func (this Deque) LastIndex() int { return this.Last.Idx } // 队首入队 func (this *Deque) OfferFirst(idx int, val int) bool { if this.IsEmpty() { this.First = &Node{Idx: idx, Val: val} this.Last = this.First return true } this.First.Left = &Node{Idx: idx, Val: val, Right: this.First} this.First = this.First.Left return true } // 队尾入队 func (this *Deque) OfferLast(idx int, val int) bool { if this.IsEmpty() { this.First = &Node{Idx: idx, Val: val} this.Last = this.First return true } this.Last.Right = &Node{Idx: idx, Val: val, Left: this.Last} this.Last = this.Last.Right return true } // 队首出队 func (this *Deque) PollFirst() *Node { if this.IsEmpty() { return nil } res := this.First if this.First == this.Last { this.First = nil this.Last = nil return res } this.First = this.First.Right this.First.Left = nil return res } // 队尾出队 func (this *Deque) PollLast() *Node { if this.IsEmpty() { return nil } res := this.Last if this.First == this.Last { this.First = nil this.Last = nil return res } this.Last = this.Last.Left this.Last.Right = nil return res } func maxSlidingWindow(nums []int, k int) []int { n := len(nums) ans := make([]int, n-k+1) var ql Deque for i, v := range nums { // 维护窗口大小 for !ql.IsEmpty() && i-ql.FirstIndex() >= k { ql.PollFirst() } // 维护单调队列 for !ql.IsEmpty() && ql.getLast() < v { ql.PollLast() } ql.OfferLast(i, v) if i-k+1 >= 0 { ans[i-k+1] = ql.getFirst() } } return ans }
70分~,这道题还是建议使用C++,否则很容易内存超出(MLE)或者时间超出(TLE)。
import java.io.*; import java.util.ArrayDeque; import java.util.Deque; import java.util.Scanner; public class Main { static int[] minSlidingWindow(int[] nums, int k) { int n = nums.length; int[] ans = new int[n-k+1]; Deque<Integer[]> ql = new ArrayDeque<Integer[]>(); for (int i = 0; i < n; i++) { while (!ql.isEmpty() && i-ql.peekFirst()[0] >= k) ql.pollFirst(); Integer[] t = {i, nums[i]}; while (!ql.isEmpty() && ql.peekLast()[1] > nums[i]) ql.pollLast(); ql.offerLast(t); if (i-k+1 >= 0) ans[i-k+1] = ql.peekFirst()[1]; } return ans; } static int[] maxSlidingWindow(int[] nums, int k) { int n = nums.length; int[] ans = new int[n-k+1]; Deque<Integer[]> ql = new ArrayDeque<Integer[]>(); for (int i = 0; i < n; i++) { while (!ql.isEmpty() && i-ql.peekFirst()[0] >= k) ql.pollFirst(); Integer[] t = {i, nums[i]}; while (!ql.isEmpty() && ql.peekLast()[1] < nums[i]) ql.pollLast(); ql.offerLast(t); if (i-k+1 >= 0) ans[i-k+1] = ql.peekFirst()[1]; } return ans; } public static void main(String[] args) { Scanner sc = new Scanner(System.in); PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out))); int n = sc.nextInt(); int k = sc.nextInt(); int[] nums = new int[n]; for (int i = 0; i < n; i++) { nums[i] = sc.nextInt(); } int[] ans1 = minSlidingWindow(nums, k); int[] ans2 = maxSlidingWindow(nums, k); for (int i = 0; i < n-k+1; i++) { out.print(ans1[i]); if (i != n-k) out.print(" "); } out.println(); out.flush(); for (int i = 0; i < n-k+1; i++) { out.print(ans2[i]); if (i != n-k) out.print(" "); } out.flush(); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。