劍指offer(59)——滑動視窗的最大值
一、題目描述
給定一個陣列 nums 和滑動視窗的大小 k,請找出所有滑動視窗裡的最大值。
示例:
輸入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3
輸出: [3,3,5,5,6,7]
解釋:
滑動視窗的位置 最大值
--------------- -----
[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
二、解題思路
輸出陣列大小計算,假設陣列長度為n,視窗大小為k,則陣列長度為 n - k + 1,其中n-k為視窗可以移動的距離,然後需要加上視窗本身。如圖所示,陣列長度為8,視窗大小為3,則輸出的陣列大小為6。
1、思路一:暴力法
按照題目要求找到視窗的邊界,在視窗中找到最大值然後移動視窗。
1.1 程式碼實現
public int[] maxSlidingWindow(int[] nums, int k) {
if(nums.length < k || k == 0 || nums.length == 0)
return new int[0];
int[] res = new int[nums.length-k+1];
int index = 0;
for(int i = k-1;i<nums.length;i++){
int temp = - Integer.MAX_VALUE,j=0,n=i;
while(j<k){
temp = Math.max(temp,nums[n--]);
j++;
}
res[index++] = temp;
}
return res;
}
1.2 複雜度分析
這種演算法時間複雜度很高,需要比較 (n-k+1)*k 次
- 時間複雜度:O(n*k),k為滑動視窗的大小
- 空間複雜度:O(1),輸出說需要的陣列不算,需要常數級的空間
2、思路二:雙端佇列
思路一中每個滑動視窗找最大值都要全部比較一次,上一次找到的最大值懟於下一次找最大值沒有幫助,這是我們對思路的演算法進行優化的切入點。
2.1 演算法思路
採用雙端佇列,維護一個單調佇列,使得滑動視窗每前進一步,原佇列的佇列頭為上個視窗的最大值,前進一步後,視窗中的每一個值都與佇列中的隊尾元素進行比較,刪除佇列中所有比當前元素小的值,然後插入該元素,繼續遍歷下一個元素,最後佇列的頭一定是佇列中最大的元素。
2.2 程式碼實現
public int[] maxSlidingWindow(int[] nums, int k) {
int len = nums.length;
if(len == 0 || k==0 || len < k){
return nums;
}
Deque<Integer> deque = new LinkedList<>();
//陣列長度減去視窗大小為視窗移動的距離
int[] res = new int[len - k + 1];
//陣列的下標
int index = 0;
//未形成視窗區間
for(int i = 0;i < k;i++){
//佇列不為空,當前值與佇列尾部比較,如果大於,刪除佇列尾部值
//一直迴圈刪除到佇列中的值都大於當前值,或者刪除到佇列為空
//即刪除佇列中小於當前值的數
while(!deque.isEmpty() && nums[i] > deque.getLast()){
deque.removeLast();
}
//執行完上面的迴圈後,佇列中要麼為空,要麼都比當前值大,然後就把當前值新增到佇列尾部
deque.addLast(nums[i]);
}
//視窗區間剛形成後,把佇列首位值新增到佇列中
//因為視窗形成後,就需要把佇列首位新增到陣列中,下面的迴圈跳過了這一步
res[index++] = deque.getFirst();
//視窗區間形成
for(int i = k;i < len;i++){
//i-k已經是區間外了,如果首位等於nums[i-k](首位為最大的數),
//那麼說明此時首位已經不在區間內了,需要刪除
if(deque.getFirst() == nums[i - k]){
deque.removeFirst();
}
//刪除佇列中比當前值小的數
while(!deque.isEmpty() && nums[i] > deque.getLast()){
deque.removeLast();
}
deque.addLast(nums[i]);
res[index++] = deque.getFirst();
}
return res;
}
2.3 複雜度分析
- 時間複雜度:O(n),遍歷陣列nums一次需要O(n);每個元素最多僅入隊出隊一次,單調佇列佔用O(2n)。
- 空間複雜度:O(k),雙端佇列中最多同時存在k個元素(k為視窗大小)。
相關文章
- 力扣 - 劍指 Offer 59 - I. 滑動視窗的最大值力扣
- [劍指offer題解][Java]佇列的最大值/滑動視窗的最大值Java佇列
- 劍指 Offer 59 - II. 佇列的最大值佇列
- 滑動視窗的最大值
- 滑動視窗的最大值問題
- 239. 滑動視窗最大值
- 滑動視窗最大值問題
- JZ-064-滑動視窗的最大值
- 滑動視窗最大值的golang實現Golang
- [Python手撕]滑動視窗最大值Python
- LeetCode 239. 滑動視窗最大值LeetCode
- 滑動視窗最大值——棧與佇列佇列
- 滑動視窗與雙指標指標
- 騰訊面試題-求滑動視窗的最大值面試題
- 演算法題:返回滑動視窗中的最大值演算法
- 劍指OFFER
- [每日一題] 第二十六題:滑動視窗的最大值每日一題
- mysql視窗函式中的滑動視窗MySql函式
- [Leetcode]雙項佇列解決滑動視窗最大值難題LeetCode佇列
- Flink的滾動視窗、會話視窗、滑動視窗及其應用會話
- Leetcode 239 滑動視窗最大值 與堆排序kotlin語言(超時)LeetCode排序Kotlin
- 細聊滑動視窗
- 滑動視窗專題
- Sentinel 原理-滑動視窗
- Leetcode 239. 滑動視窗最大值 (Java實現 超詳細註釋!)LeetCodeJava
- 劍指offer導航
- Leetcode劍指offer(八)LeetCode
- 劍指offer16
- 劍指 offer20
- 劍指 offer21
- 滑動視窗演算法演算法
- 【劍指offer】【2】字串的空格字串
- 滑動視窗問題總結
- WeetCode2滑動視窗系列
- 滑動視窗法——Leetcode例題LeetCode
- TCP 流量控制-滑動視窗TCP
- 滑動視窗演算法思路演算法
- Sentinel滑動視窗演算法演算法