日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

Leetcode 295. 数据流的中位数

發(fā)布時(shí)間:2025/5/22 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Leetcode 295. 数据流的中位数 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1.題目要求

中位數(shù)是有序列表中間的數(shù)。如果列表長(zhǎng)度是偶數(shù),中位數(shù)則是中間兩個(gè)數(shù)的平均值。

例如,

[2,3,4]?的中位數(shù)是 3

[2,3] 的中位數(shù)是 (2 + 3) / 2 = 2.5

設(shè)計(jì)一個(gè)支持以下兩種操作的數(shù)據(jù)結(jié)構(gòu):

  • void addNum(int num) - 從數(shù)據(jù)流中添加一個(gè)整數(shù)到數(shù)據(jù)結(jié)構(gòu)中。
  • double findMedian() - 返回目前所有元素的中位數(shù)。

示例:

addNum(1)addNum(2)findMedian() -> 1.5addNum(3) findMedian() -> 2

進(jìn)階:

  • 如果數(shù)據(jù)流中所有整數(shù)都在 0 到 100 范圍內(nèi),你將如何優(yōu)化你的算法?
  • 如果數(shù)據(jù)流中 99% 的整數(shù)都在 0 到 100 范圍內(nèi),你將如何優(yōu)化你的算法?
  • ?

    ?

    2.解題思路

    堆是一個(gè)非常重要的數(shù)據(jù)結(jié)構(gòu),堆排序在C++中的實(shí)現(xiàn)為優(yōu)先級(jí)隊(duì)列(Priority_queue),關(guān)于這一點(diǎn),我的另一篇博文 "Leetcode 703. 數(shù)據(jù)流中的第K大元素"? 有更詳細(xì)提到,這里不做重復(fù)。

    LeetCode網(wǎng)站把這一道劃分在“堆”一類中,也是提醒我們使用堆結(jié)構(gòu)。這道題很巧妙,我是聽(tīng)了算法課(牛客網(wǎng)的左程云大牛)的講解才弄明白。這里的代碼是自己聽(tīng)懂了思路,獨(dú)立寫(xiě)出來(lái)的。

    關(guān)鍵思路:建立兩個(gè)堆(使用priority_queue實(shí)現(xiàn)),一個(gè)大根堆,一個(gè)小根堆。

    ? ? ? ? ? (1)一個(gè)大根堆保存所有整數(shù)中較小的1/2;一個(gè)小根堆保存所有整數(shù)中較大的1/2
    ????????? (2)并且,依次添加元素過(guò)程中,兩個(gè)堆元素個(gè)數(shù)的差的絕對(duì)值不能超過(guò)1

    ? ? ? ? ? ? ? ?? 這樣,兩個(gè)堆建立好了以后,

    ? ? ? ? ? (1)如果輸入的元素個(gè)數(shù) n 是偶數(shù),則兩個(gè)堆的元素個(gè)數(shù)相等,分別取大根堆的頂和小根堆的頂,取平均值,即是所求的整個(gè)數(shù)據(jù)流的中位數(shù);

    ? ? ? ? ? (2)如果輸入的元素個(gè)數(shù) n 是奇數(shù),則必有一個(gè)堆的元素個(gè)數(shù)為(n/2+1),返回這個(gè)堆的頂,即為所求的中位數(shù)。

    ?

    3.我的代碼

    ? ? ? ? 個(gè)人比較喜歡寫(xiě)段落注釋行注釋,因?yàn)檫@樣自己一年之后還能快速看懂,當(dāng)然也方便他人,特別是一起刷題的伙伴,輕松看懂。

    ? ? ? ? 更多的細(xì)節(jié)講解里都在注釋里。如有錯(cuò)誤的地方,歡迎多指正。

    ? ? ? ? 代碼通過(guò)所有測(cè)試案例的時(shí)間為124ms。 ? ? ? ?

    class MedianFinder { public:/** initialize your data structure here. */MedianFinder() {}void addNum(int num) {/*建立兩個(gè)堆:(1)一個(gè)大根堆,保存所有整數(shù)中較小的1/2;一個(gè)小根堆,保存所有整數(shù)中較大的1/2;(2)并且,依次添加元素過(guò)程中,兩個(gè)堆大小的差的絕對(duì)值不能超過(guò)1; *///第一元素加入大根堆if(heap1.size()==0){heap1.push(num);return;}if(num<=heap1.top()){//第二個(gè)元素比大根堆的頂小 heap1.push(num);//大根堆元素過(guò)多if(heap1.size()-heap2.size()>1){int temp = heap1.top();heap1.pop();heap2.push(temp);//大根堆彈出頂?shù)叫「? }}else{//第二個(gè)元素比大根堆的頂大,直接進(jìn)入小根堆 heap2.push(num);//小根堆元素過(guò)多if(heap2.size()-heap1.size()>1){int temp = heap2.top();heap2.pop();heap1.push(temp);//小根堆彈出頂?shù)酱蟾? }}}double findMedian() {//輸入的元素為奇數(shù)個(gè)if(heap1.size() > heap2.size())return heap1.top();else if(heap1.size() < heap2.size())return heap2.top();//輸入的元素個(gè)數(shù)為偶數(shù)elsereturn (heap1.top()+heap2.top())/2.0; //取大根堆、小根堆的堆頂元素取平均值,即為所求全局中位數(shù) }private:priority_queue<int> heap1;//默認(rèn),大根堆priority_queue<int,vector<int>,greater<int>> heap2;//小根堆(升序序列) };/*** Your MedianFinder object will be instantiated and called as such:* MedianFinder obj = new MedianFinder();* obj.addNum(num);* double param_2 = obj.findMedian();*/

    ??

    4.用時(shí)更少的示例代碼

    ?這是我提交解答后,查看細(xì)節(jié),看到的Leetcode官網(wǎng)上提交的關(guān)于這道題運(yùn)行時(shí)間最短(96ms)的示例代碼。

    ?LeetCode上刷好多速度排名第一的代碼中都有一段類似的代碼,就是下面代碼中的第一段代碼——優(yōu)化C++的IO速度。

    /*一般地,C++的運(yùn)行速度不如C的,主要原因是C++的輸入輸出流兼容了C的輸入輸出,因此,C++的速度才會(huì)變慢,
    如果去掉C++的輸入輸出的兼容性的話,速度就和C的差不多了
    */
    static const auto __ = []() {// turn off syncstd::ios::sync_with_stdio(false);// untie in/out streams std::cin.tie(nullptr);return nullptr; }();class MedianFinder { public:/** initialize your data structure here. *///使用vector實(shí)現(xiàn)兩個(gè)堆,而不是priority_queuevector<int> maxheap;vector<int> minheap;bool flag = true;MedianFinder() { }void addNum(int num) {if(flag){//構(gòu)建小根堆if(minheap.size()>0&&num>minheap[0]){minheap.push_back(num);push_heap(minheap.begin(),minheap.end(),greater<int>()); num = minheap[0];pop_heap(minheap.begin(),minheap.end(),greater<int>());minheap.pop_back();}maxheap.push_back(num);push_heap(maxheap.begin(),maxheap.end(),less<int>());flag=false;}else{//構(gòu)建大根堆if(maxheap.size()>0&&num<maxheap[0]){maxheap.push_back(num);push_heap(maxheap.begin(),maxheap.end(),less<int>());num = maxheap[0];pop_heap(maxheap.begin(),maxheap.end(),less<int>());maxheap.pop_back();}minheap.push_back(num);push_heap(minheap.begin(),minheap.end(),greater<int>()); flag=true;}}double findMedian() {if(maxheap.size()<1&&minheap.size()<1)return 0;if(flag){return (maxheap[0]+minheap[0])/2.0; }else{return maxheap[0];}} };/*** Your MedianFinder object will be instantiated and called as such:* MedianFinder obj = new MedianFinder();* obj.addNum(num);* double param_2 = obj.findMedian();*/

    ?

    參考博客:

    ? ? ? https://blog.csdn.net/xiaosshhaa/article/details/78136032 ?? std::ios::sync_with_stdio(false); cin.tie(0);

    ?

    轉(zhuǎn)載于:https://www.cnblogs.com/paulprayer/p/9884332.html

    總結(jié)

    以上是生活随笔為你收集整理的Leetcode 295. 数据流的中位数的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。