1.1、題目1

劍指 Offer 59 - I. 滑動視窗的最大值

1.2、解法

解題思路:(來自作者bigbeats)

相當於維護一個最大佇列(隊頭元素最大,向隊尾非嚴格遞減)

在未形成視窗前,先構造完整視窗。
在形成視窗後,移動視窗: 判斷即將失去的這個左邊界值是否是最大值,如果是需要從最大佇列中刪除這個最大值。
再讓佇列尾部開始與即將加入的右邊界值做對比,如果佇列尾部元素大於或等於這個元素,則將這個元素加入尾部,反之將尾部元素刪除。 以上兩步操作保證佇列的順序是非嚴格遞減的,即隊頭存放最大值。且佇列中元素的生命週期都在對應的視窗期內。

1.3、程式碼


class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
if(nums == null || k == 0) return new int[]{};
Deque<Integer> q = new LinkedList<>(); // 形成最初的視窗
for(int i = 0;i <= k - 1;++i){
while(!q.isEmpty() && q.peekLast() < nums[i]){
q.removeLast();
}
q.offerLast(nums[i]);
}
int[] res = new int[nums.length - k + 1];
res[0] = q.peekFirst();
if(nums[0] == q.peekFirst()){
q.removeFirst();
} // 視窗已經形成
for(int i = k;i <= nums.length -1;++i){
while(!q.isEmpty() && q.peekLast() < nums[i]){
q.removeLast();
}
q.offerLast(nums[i]);
res[i-k+1] = q.peekFirst();
if(nums[i-k+1] == q.peekFirst()){
q.removeFirst();
}
}
return res;
}
}

2.1、題目2

劍指 Offer 59 - II. 佇列的最大值

2.2、解法

這裡用兩個佇列來解決,queue用來存放當前放置的內容,deque來存放一定數量的大數

最大值則直接取queue降序的頭,push時,則將deque中小於它的數去掉,將該值新增到佇列末尾。

pop時,判斷deque的頭是否是推出的頭,是的話也將該數值推出。

2.3、程式碼

class MaxQueue {
Queue<Integer> q;
Deque<Integer> d; public MaxQueue() {
q = new LinkedList<Integer>();
d = new LinkedList<Integer>();
} public int max_value() {
if (d.isEmpty()) {
return -1;
}
return d.peekFirst();
} public void push_back(int value) {
while (!d.isEmpty() && d.peekLast() < value) {
d.pollLast();
}
d.offerLast(value);
q.offer(value);
} public int pop_front() {
if (q.isEmpty()) {
return -1;
}
int ans = q.poll();
if (ans == d.peekFirst()) {
d.pollFirst();
}
return ans;
}
}