生活随笔
收集整理的這篇文章主要介紹了
LeetCode 480. 滑动窗口中位数(大小堆升级版+set实现)
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
1. 題目
中位數(shù)是有序序列最中間的那個(gè)數(shù)。
如果序列的大小是偶數(shù),則沒有最中間的數(shù);此時(shí)中位數(shù)是最中間的兩個(gè)數(shù)的平均數(shù)。
例如:
[2,3,4],中位數(shù)是 3
[2,3],中位數(shù)是 (2 + 3) / 2 = 2.5
給你一個(gè)數(shù)組 nums,有一個(gè)大小為 k 的窗口從最左端滑動(dòng)到最右端。
窗口中有 k 個(gè)數(shù),每次窗口向右移動(dòng) 1 位。
你的任務(wù)是找出每次窗口移動(dòng)后得到的新窗口中元素的中位數(shù),并輸出由它們組成的數(shù)組。
示例:
給出 nums
= [1,3,-1,-3,5,3,6,7],以及 k
= 3。窗口位置 中位數(shù)
--------------- -----
[1 3 -1] -3 5 3 6 7 11 [3 -1 -3] 5 3 6 7 -11 3 [-1 -3 5] 3 6 7 -11 3 -1 [-3 5 3] 6 7 31 3 -1 -3 [5 3 6] 7 51 3 -1 -3 5 [3 6 7] 6因此,返回該滑動(dòng)窗口的中位數(shù)數(shù)組
[1,-1,-1,3,5,6]。提示:
你可以假設(shè) k 始終有效,即:k 始終小于輸入的非空數(shù)組的元素個(gè)數(shù)。
與真實(shí)值誤差在
10 ^ -5 以內(nèi)的答案將被視作正確答案。
來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/sliding-window-median
著作權(quán)歸領(lǐng)扣網(wǎng)絡(luò)所有。商業(yè)轉(zhuǎn)載請聯(lián)系官方授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。
2. 解題
類似題目:
LeetCode 295. 數(shù)據(jù)流的中位數(shù)(大小堆)
LeetCode 703. 數(shù)據(jù)流中的第K大元素(優(yōu)先隊(duì)列)
參考我的博客 數(shù)據(jù)結(jié)構(gòu) 堆(優(yōu)先隊(duì)列)
參考大小堆的思想,一個(gè)堆最多比另一個(gè)堆最多多一個(gè)元素,不再多講,請參考上面鏈接
- 關(guān)鍵要實(shí)現(xiàn)從堆中刪除窗口左端點(diǎn),那么用 set 來當(dāng)做堆就可以突破優(yōu)先隊(duì)列(堆)不能刪除非堆頂元素
- 本題:小堆size = 大堆size or 小堆size = 大堆size+1
- k 為 奇數(shù),直接返回小堆頂 set.begin()
- k 為 偶數(shù),返回兩個(gè)堆頂?shù)钠骄?/li>
class Solution { multiset
<int> minheap
;multiset
<int,greater
<int>> maxheap
;
public:vector
<double> medianSlidingWindow(vector
<int>& nums
, int k
) {if(k
== 1) return vector
<double>(nums
.begin(), nums
.end());int n
= nums
.size(), i
= 0, j
= 0, idx
= 0;long a
, b
;vector
<double> ans(n
-k
+1);for( ; j
< k
; ++j
)maxheap_minheap_add(nums
[j
]);a
= (*maxheap
.begin()), b
= (*minheap
.begin());ans
[idx
++] = (k
&1) ? b
: (a
+b
)/2.0;for(i
= 0 ; j
< n
; ++i
,++j
){maxheap_minheap_del(nums
[i
]);maxheap_minheap_add(nums
[j
]);a
= (*maxheap
.begin()), b
= (*minheap
.begin());ans
[idx
++] = (k
&1) ? b
: (a
+b
)/2.0;}return ans
;}void maxheap_minheap_add(int x
){if(minheap
.empty())minheap
.insert(x
);else if(maxheap
.size() == minheap
.size()){if(x
>= *maxheap
.begin())minheap
.insert(x
);else{minheap
.insert(*maxheap
.begin());maxheap
.erase(maxheap
.begin());maxheap
.insert(x
);}}else if(maxheap
.size() < minheap
.size()){if(x
<= *minheap
.begin())maxheap
.insert(x
);else{maxheap
.insert(*minheap
.begin());minheap
.erase(minheap
.begin());minheap
.insert(x
);}}}void maxheap_minheap_del(int x
){if(maxheap
.size() < minheap
.size()){auto it
= minheap
.find(x
);if(it
!= minheap
.end())minheap
.erase(it
);else{maxheap
.erase(maxheap
.find(x
));maxheap
.insert(*minheap
.begin());minheap
.erase(minheap
.begin());}}else if(maxheap
.size() == minheap
.size()){auto it
= maxheap
.find(x
);if(it
!= maxheap
.end())maxheap
.erase(it
);else{minheap
.erase(minheap
.find(x
));minheap
.insert(*maxheap
.begin());maxheap
.erase(maxheap
.begin());}}}
};
108 ms 18.9 MB
總結(jié)
以上是生活随笔為你收集整理的LeetCode 480. 滑动窗口中位数(大小堆升级版+set实现)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。