LeetCode算法學習之--Queue--滑動窗口最大值

這是我參與8月更文挑戰的第8天,活動詳情查看:8月更文挑戰javascript

你們好今天給你們分享下一道 LeetCode 困難難度 的題目滑動窗口最大值前端

題目

給你一個整數數組 nums,有一個大小爲 k 的滑動窗口從數組的最左側移動到數組的最右側。你只能夠看到在滑動窗口內的 k 個數字。滑動窗口每次只向右移動一位。java

返回滑動窗口中的最大值。算法

示例 1:

輸入: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
示例 2:

輸入:nums = [1], k = 1
輸出:[1]
示例 3:

輸入:nums = [1,-1], k = 1
輸出:[1,-1]
示例 4:

輸入:nums = [9,11], k = 2
輸出:[11]
示例 5:

輸入:nums = [4,-2], k = 2
輸出:[4]

來源:力扣(LeetCode)
連接:https://leetcode-cn.com/problems/sliding-window-maximum
著做權歸領釦網絡全部。商業轉載請聯繫官方受權,非商業轉載請註明出處。

複製代碼

分析

1.滑動窗口中有k個數數組

2.返回存放每一個滑動窗口中最大值的數組markdown

解法網絡

1.雙指針app

2.雙端隊列oop

解法一:暴力雙指針(超時)

思路
1.迭代,在每次迭代中放入2個指針 一前一後
2.每次迭代計算2個指針直接的最大值
3.更新最大值
*/

var maxSlidingWindow = function (nums, k) {
  const res = [];

  for (let i = 0; i < nums.length - k + 1; i++) {
    let max = -Infinity;
    for (let j = i; j < i + k; j++) {
      max = Math.max(max, nums[j]);
    }
    res.push(max);
  }

  return res;
};

/* 複雜度 時間 O(n(n-k+1)) 空間 O(n-k+1) */


複製代碼

解法二:雙端隊列

代碼轉載:leetcode-cn.com/problems/sl…post

思路
1.所謂雙端隊裏就是兩端均可以出入
2.核心思想就是 在隊列中的第一個元素存放最大的元素索引,
3.若是有新來的元素分以下的幾種狀況
    1.新來的元素大於隊尾的元素,則把隊尾元素排除隊列,在繼續比較隊尾元素
    直到找到比它大的值,而後把新元素的索引推入隊尾
    2.若是新元素小於隊尾元素且,隊列中的元素個數小於k,則吧新元素索引直接放入隊尾
    3.若是新元素比全部的元素都大,則排序全部的隊列裏面的索引,把新元素的索引放入隊首
4.在移動右邊窗口的時候一旦發現,隊首的索引等於i-k則從隊首排除
*/
var maxSlidingWindow = function (nums, k) {
  // 雙端隊列
  const queue = [];
  const res = [];
  // 先處理前K個元素
  for (let i = 0; i < k; i++) {
    maintainQueue(queue, i);
  }

  // 把前k個元素的最大值放入隊列中
  res.push(nums[queue[0]]);

  // 處理後面的元素的
  for (let i = k; i < nums.length; i++) {
    //在隊列中處理新加入的元素
    maintainQueue(queue, i);

    //只有一種狀況 隊首須要出隊,就是等於滑動窗口的左邊界的左邊第一個元素的索引
    if (queue[0] === i - k) {
      queue.shift();
    }
    // 添加當前滑動窗口的值
    res.push(nums[queue[0]]);
  }

  return res;

  function maintainQueue(queue, i) {
    // 若是大於隊尾 則隊尾從尾部出隊列,繼續比較隊尾元素
    while (queue.length && nums[i] >= nums[queue[queue.length - 1]]) {
      queue.pop();
    }
    // 直到隊列爲空或者找到了比新元素大的隊尾元素
    queue.push(i);
  }
};
/* 複雜度 時間 O(n) 空間 O(k) */
複製代碼

1.png

總結

這道題考察的是對雙端隊列的使用,如何用隊列來存放最大值,何時從隊列中釋放元素,比較好理解,須要多多練習

你們能夠看看我分享的一個專欄(前端搞算法)裏面有更多關於算法的題目的分享,但願可以幫到你們,我會盡可能保持天天晚上更新,若是喜歡的麻煩幫我點個贊,十分感謝

你們若是對「TS」感興趣的能夠看看個人專欄 (TypeScript經常使用知識),感謝你們的支持

文章內容目的在於學習討論與分享學習算法過程當中的心得體會,文中部分素材來源網絡,若有侵權,請聯繫刪除,郵箱 182450609@qq.com

相關文章
相關標籤/搜索