LeetCode 239:滑動窗口最大值 思考分析

給定一個數組 nums,有一個大小為 k 的滑動窗口從數組的最左側移動到數組的最右側。你只可以看到在滑動窗口內的 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

提示:

1 <= nums.length <= 10^5
-10^4 <= nums[i] <= 10^4
1 <= k <= nums.length

暴力求解:超時

class Solution {
public:vector<int> maxSlidingWindow(vector<int>& nums, int k) {int maxnum=-10001;vector<int> result;int n= nums.size();//1、如果k> = nums.size,   if(k>=n){for(int i=0;i<n;i++){if(nums[i]>=maxnum) maxnum=nums[i];}result.push_back(maxnum);return result;}//2、如果k<nums.sizeelse{int left=0;int right=0;for(left = 0;left<=n-k;left++){//更新左右邊界right=left+k-1;//更新最小值maxnum=-10001;for(int x=left;x<=right;x++){if(nums[x]>=maxnum) maxnum=nums[x]; }result.push_back(maxnum);}return result;}}
};

優化思路:
可以想到暴力方法肯定是有時間浪費的,在滑窗移動的時候,滑窗內插入一個新值,消失了一個舊值,有k-1個值仍然保留著。
我們只需要比較一下新插入的值和舊的k-1個值中的最大值,將得到的最大值賦給結果數組就可以了。
一開始我想的是用兩個容量為2的數組,分別存放第一大的數值和它的下標,第二大的數值和它的下標,但是在推導的時候發現一個問題:
錯誤代碼,具體疑問見代碼注釋:

class Solution {
public:vector<int> maxSlidingWindow(vector<int>& nums, int k) {int maxnum[2]={-10001,-10001};      //存儲當前滑窗內第一大和第二大的數值int index[2]={0,0};                 //存儲當前滑窗內第一大和第二大的數值的下標vector<int> result;int n= nums.size();if(k*n==0) return result;//1、如果k> = nums.size,   if(k>=n){for(int i=0;i<n;i++){if(nums[i]>=maxnum[0]) maxnum[0]=nums[i];}result.push_back(maxnum[0]);return result;}//2、如果k<nums.sizeelse{int left=0;int right=0;//將前k個數進行裝載for(int i=0;i<k;i++){//nums[i]比第一大還大,更新第一大if(nums[i]>=maxnum[0]){maxnum[0]=nums[i];   //第一大裝載完畢index[0]=i;  } //第二大的范圍:大于等于舊的第二大,小于等于新的第一大,并且不能是第一大的數if(nums[i]>=maxnum[1] && nums[i]<=maxnum[0] && index[0]!=i){maxnum[1]=nums[i];   //第二大裝載完畢index[1]=i;  }}left=1;//從第k+1個數開始for(right = k;right<n;right++,left++)  {//如果移動的時候將最大值拋棄if(index[0]<left){//比較第二大的值和新插入的值的大小,獲取最大值//如果第二大值比新插入值大,則第二大值變為最大值,但是新插入的值不一定是第二大值//所以我們需要構建一個從大到小排列的雙端隊列!if(maxnum[1]>=)}result.push_back(maxnum);}return result;}}
};

發現需要構建一個從大到小排列的雙端隊列
1、新的數入隊列,并按照其大小排列,然后將比它小的數全部出隊列(因為我們需要的是最大值,只要隊列中有數比新入隊列的數要小就說明它們絕對不可能是最大值,最大值最起碼也是大于等于新入隊列的數)。
2、觀察隊首(數值最大)的索引值是否在[left,right]之間,如果不在就出隊列,直到隊首索引值滿足在[left,right]之間

class Solution {
public:vector<int> maxSlidingWindow(vector<int>& nums, int k) {vector<int> result;int n= nums.size();if(n==0 ||k==0) return result;if(k>=n){auto maxPosition = max_element(nums.begin(), nums.end());result.push_back(*maxPosition);return result;}//2、如果k<nums.sizeelse{int left=0;int right=0;// 雙向隊列 保存當前窗口最大值的數組位置 保證隊列中數組位置的數值按從大到小排序deque< int> Dq;// 遍歷nums數組for(int i = 0;i < n;i++){// 保證從大到小 如果前面數小則需要依次彈出,直至滿足要求//如果隊尾的元素小于Nums[i],隊尾元素出隊列while(Dq.size() && nums[Dq.back()] <= nums[i]){Dq.pop_back();}// 將當前數組下標入隊列Dq.push_back(i);if(i>=k-1){// 判斷當前隊列中隊首是否有效,如果隊首小于左邊界,則將隊首出隊列,直到隊首元素符合要求while(Dq.size() && Dq.front() <= i-k){Dq.pop_front(); }result.push_back(nums[Dq.front()]);}}return result;}}
};

雖然AC了,但是效率不高,不過基本思路是符合大眾的:
在這里插入圖片描述
不過上述的寫法仍然有些不簡潔,這里貼一下比較簡潔的寫法:
https://leetcode-cn.com/problems/sliding-window-maximum/solution/dan-diao-dui-lie-by-labuladong/
官方給出的dp思路,還得理解理解
https://leetcode-cn.com/problems/sliding-window-maximum/submissions/

class Solution {
public:vector<int> maxSlidingWindow(vector<int>& nums, int k) {int n = nums.size();vector<int> output(n-k+1,0);vector<int> left(n,0);vector<int> right(n,0);left[0]=nums[0];right[n-1]=nums[n-1];for(int i = 1;i<n;i++){if(i%k == 0) left[i]=nums[i];else left[i]=max(left[i-1],nums[i]);int j = n-i-1;if((j+1)%k == 0) right[j]=nums[j];else right[j]=max(right[j+1],nums[j]);}for(int i = 0;i < n-k+1;i++)output[i] = max(left[i+k-1],right[i]);return output;}
};

為什么:兩數組一起可以提供兩個塊內元素的全部信息。
考慮從下標 i 到下標 j的滑動窗口。 根據定義,right[i] 是左側塊內的最大元素, left[j] 是右側塊內的最大元素。因此滑動窗口中的最大元素為 max(right[i], left[j])

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/378108.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/378108.shtml
英文地址,請注明出處:http://en.pswp.cn/news/378108.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

計算機論文范文1500,電子商務畢業論文范文1500字

電子商務畢業論文范文1500字時間稍縱即逝&#xff0c;充滿意義的大學生活即將結束&#xff0c;畢業前要通過最后的畢業論文&#xff0c;畢業論文是一種有計劃的檢驗學生學習成果的形式&#xff0c;那么問題來了&#xff0c;畢業論文應該怎么寫&#xff1f;下面是小編為大家整理…

為什么要使用反射機制

1、反射的構造過程 直接構造 1、加載程序集 2、根據類名構造 反射構造 1、加載程序集 2、查找需要構造類的類名 3、根據類名構造 注意&#xff1a; 能不用反射還是別用反射,因為畢竟要以性能做為代價, 不過在某些特定場合,還是只能用它,所以要自己根據實際情況來…

java uuid靜態方法_Java UUID timestamp()方法與示例

java uuid靜態方法UUID類timestamp()方法 (UUID Class timestamp() method) timestamp() method is available in java.util package. timestamp()方法在java.util包中可用。 timestamp() method is used to return the timestamp linked with this UUID. timestamp()方法用于返…

ANT:編譯SWC

編譯SWC使用的是compc任務&#xff0c;compc需要幾個重要的參數&#xff1a; 1、輸出路徑 2、包含的類 3、源路徑 其中第2個參數是比較難拿到的&#xff0c;需要使用ANT的幾個其他的方法來將路徑轉換了類的完整路徑&#xff0c;先看完整的代碼&#xff1a; <target name&quo…

ssm整合事務失效

<!-- 開啟注解驅動的事務管理 --><tx:annotation-driven transaction-manager"transactionManager"/>原因&#xff1a;未開啟spring事務驅動

五、規則組織的衍生組織——緯山形組織數學模型的建立

基礎概念公式推到可參考該專欄下的前幾篇博文。 緯山形組織圖&#xff1a; 觀察可知&#xff1a;緯山形組織圖下半部分是右斜組織&#xff0c;上半部分是左斜組織。右斜和左斜按照垂直方向進行排列。 該圖是一個2上3下2上1下(從最下面一行從左往右觀看) 特點&#xff1a;每一…

批處理設置計算機不休眠,虛擬機狀態下怎樣設置電腦不休眠

簽中&#xff0c;在“啟用休眠”項打勾即可啟用休眠功能。如果此項不可用&#xff0c;則說明你的電源不支持休眠功能。或如果你安裝了還原精靈等一些保護軟件&#xff0c;也無法啟用休眠功能。2 打開電腦的休眠功能后&#xff0c;在“電源選項”的“電源使用方案”標簽中&#…

HDU 2836 Traversal 簡單DP + 樹狀數組

題意&#xff1a;給你一個序列&#xff0c;問相鄰兩數高度差絕對值小于等于H的子序列有多少個。 dp[i]表示以i為結尾的子序列有多少&#xff0c;易知狀態轉移方程為&#xff1a;dp[i] sum( dp[j] ) 1;( abs( height[i] - height[j] ) < H ) 由abs( height[i] - height[j] …

劍指 Offer 57 - II. 和為s的連續正數序列 思考分析

輸入一個正整數 target &#xff0c;輸出所有和為 target 的連續正整數序列&#xff08;至少含有兩個數&#xff09;。 序列內的數字由小到大排列&#xff0c;不同序列按照首個數字從小到大排列。 示例 1&#xff1a; 輸入&#xff1a;target 9 輸出&#xff1a;[[2,3,4],[4…

java uuid靜態方法_Java UUID compareTo()方法與示例

java uuid靜態方法UUID類compareTo()方法 (UUID Class compareTo() method) compareTo() method is available in java.util package. compareTo()方法在java.util包中可用。 compareTo() method is used to compare two UUID objects or in other words, it is used to compar…

hdu 1214

找規律的題目。如果不是圓環形狀的話&#xff08;也就是n個人排成直線&#xff09;&#xff0c;完全調換順序需要(n-1)*n/2次交換&#xff1b;為環形的時候&#xff0c;可能不需要這么多&#xff0c;因為調換有了兩個方向。我們記直線時n個人需要的交換次數為g(n)(n-1)*n/2&…

六、規則組織的衍生組織——緯向破斜組織數學模型的建立

基礎概念公式推到可參考該專欄下的前幾篇博文。 緯向破斜組織圖&#xff1a; 下半部分(從左往右)&#xff1a;&#xff0c;3上2下2上1下&#xff0c;右斜&#xff0c;飛數為1 上半部分(從下往上)&#xff1a;&#xff0c;2上2下1上3下。左斜&#xff0c;飛數為-1 通過分析可…

車牌識別與計算機編程,基于MATLAB的車牌識別程序詳解.ppt

基于MATLAB的車牌識別程序詳解自定義一個字符函數&#xff0c;用來從車牌區域中提取出7個字符&#xff0c;其中利用切割函數來進行切割。 程序&#xff1a;function [word,result]getword(d) word[];flag0;y18;y20.5; while flag0 [m,n]size(d);%將d的尺寸存入m n wide0; while…

數據結構與算法2——數組

數組是應用最廣泛的數據存儲結構。它被植入到大部分編程語言中。大部分數據結構都有最基本的四個操作&#xff1a;插入、刪除、查找、修改。對于這四種操作每一種數據結構都有相應的算法。算法和數據結構因此就是非常緊密的相聯系的。 1 數組例子 …

java treemap_Java TreeMap putAll()方法與示例

java treemapTreeMap類putAll()方法 (TreeMap Class putAll() method) putAll() method is available in java.util package. putAll()方法在java.util包中可用。 putAll() method is used to copy all the key-value pairs from the given map (m) and paste it into this map…

LeetCode 167. 兩數之和 II - 輸入有序數組 思考分析

目錄1、暴力&#xff0c;超時2、雙指針滑動窗口條件限制 AC3、觀看題解&#xff08;吸取他人經驗&#xff09;1、二分查找2、雙指針3、雙指針二分查找給定一個已按照升序排列 的有序數組&#xff0c;找到兩個數使得它們相加之和等于目標數。 函數應該返回這兩個下標值 index1 …

敏捷開發用戶故事系列之七:用戶故事與MVC

這是用戶故事系列的第七篇。&#xff08;之一&#xff0c;之二&#xff0c;之三&#xff0c;之四&#xff0c;之五&#xff0c;之六&#xff0c;之七&#xff0c;之八&#xff0c;之九&#xff09;用戶故事和MVC沒有關系&#xff0c;因為MVC是實現方法&#xff0c;因此在思考用…

七、規則組織的衍生組織——菱形斜紋組織數學模型的建立

基礎概念公式推到可參考該專欄下的前幾篇博文。 菱形斜紋組織圖&#xff1a; 分析&#xff1a;首先3上2下2上1下&#xff0c;飛數為1&#xff0c;右斜。kw8表示從左下角開始往上數8格為緯峰所在位置&#xff1b;kj8表示從左上角開始往右數8格為經峰所在位置。 這樣就將菱形斜…

顯卡測試軟件毛毛蟲,超龍超龍,與眾不同,頂流配備,散熱一流,3070Ti超龍旗艦版評測...

可能大家都沒想到此次顯卡荒會持續近一年&#xff0c;還是出現國家級干涉才將這股“歪風”剎住了。而且也僅僅算是剎住了大陸的速度&#xff0c;主要踩死剎車的應該就是黃大廚。他從5月初推出的新核心就采取了出廠即鎖算力的做法&#xff0c;但是即便如此&#xff0c;那些看著高…

poj 2513 Colored Sticks

// 判斷圖是否聯通 在連通的基礎上還要判斷是否存在歐拉通路// 判斷連通就并查集了 判斷是否存在歐拉通路&#xff1a; 點度數為數的點 1 >3就是不存在的 其它是存在的// 我開始用 map 判重 然后就悲劇了一上午 好久沒寫 Trie樹了 都忘了、#include <iostream> #in…