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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

如何轻松将上亿的数据玩弄于股掌之中?

發布時間:2023/12/4 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 如何轻松将上亿的数据玩弄于股掌之中? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.


在日常生活中,我們經常會遇到排序問題


  • 在打撲克牌的時候,原本拿到手上的牌是亂序的,我們會按照自己喜好的順序一張一張排好手上的牌,最后看起來是順眼的。比如小智打撲克牌會將自己手上的牌排成這樣:


小智排了一下手上的牌,這次手上的牌還不錯


  • 攝影師給畢業的同學們拍照片,要求同學們站好隊形,然后要求中間高,兩邊低的方式排隊。如果攝影師發現某個同學的高度跟旁邊的同學不協調,這個同學必須馬上調整自己的位置,最后是一派整齊的景象


攝影師:嗯,你們排得不錯


  • 經常泡圖書館的泡友,會發現有很多志愿者會幫忙整理圖書位置。每一本書的書背上面都有一張標簽,書架上的圖書需要按照標簽上的編號排好順序,這樣泡友才能快速找到想要的圖書。


小智的書架,是不是還算整齊?


這些例子就是排序問題了。排序問題不僅在生活中常見,在IT屆也常見。據說,某科技公司在做一個項目時遭遇大量排序問題,運算速度奇慢,項目經理非常頭痛,為招收能制伏排序問題的人才,干脆總結成了一道題目(沒想到這道題日后竟成為IT面試屆的經典)。這道題就是:


如何在一億個數當中找到最大的10000個數?


如果讓小智手工去找這些數,用一輩子的時間可能還不夠。當然我們要用計算機來算,我們不僅要考慮,計算機能夠如何找到這10000個最大的數,更重要的是找到這10000個數的時間越短越好


方法一:重復尋找法


我們可以先用最直觀的方式來做這道題目,起個名字叫重復尋找法


第1步:我們先在這一億個數當中,尋找到最大的那個數字,把它記錄下來。


第2步:從這一億個數字中,剔除這個最大的數字


第3步:重復執行第1步和第2步,直至記錄下來10000個數字。記錄下來的結果即為所求。


以挑蘋果為例重復尋找法就好比我們在蘋果堆中挑蘋果的時候,先在所有蘋果里面挑出最好的一個,然后繼續在剩余蘋果里面再挑出最好的一個……如此類推。


怎么找到最好的蘋果?那必須拿著某個蘋果,對比一遍所有蘋果,如果發現有更好的蘋果,把好的蘋果拿在手上,把次好的蘋果放下,直至對比完所有的蘋果后,手上拿著的就是最好的蘋果


重復尋找法,就好比在蘋果堆中不斷挑最大最好看的蘋果到自己的籃子里


為了方便討論起見,我們設?n = 1億


我們知道,求n個數最大值的比較次數為?n,求最大值的過程需要執行?10000?次,因此,重復尋找法的總比較次數為:


10000 × n


中場解答:


為什么這里只關注總比較次數?實際上我們在做排序的時候,比較次數與數據規模有明顯關系,而其他的計算比如賦值、代碼解析時間這些與數據規模無關,排序的關鍵是看比較次數。


為什么求最大值的比較次數為n呢?我們可以假想這樣的情景:先拿出n個數中第一個數,作為臨時最大值。在遍歷n個數的過程中,如果發現有新的數字大于臨時最大值,則以該數字為臨時最大值。遍歷完成以后,臨時最大值即真正的最大值,比較的次數只需n次。


雖然這個問題有答案了,但是心里貌似有一些遺憾,不知道大家感受到了沒?


其實,遍歷10000次,這個次數有點多,為什么不可以遍歷1次就得到結果呢?


方法二:局部淘汰法


實際上是可以的,還有一個能夠一步到位的方法,叫做局部淘汰法


第1步:先創建一個數組,保存這1億個數字中的前10000個數字,計算數組的最小數字。


第2步:遍歷剩下的數字。如果遍歷到某個數?A?大于數組的最小數字,那么則用?A?替換掉數組的最小數字。并重新計算數組的最小數字。

第3步:遍歷完成后,數組內的數字即為所求。


以打麻將為例,一開始我們拿了n個牌,局部淘汰法類似我們在打麻將過程中,如果摸到一個自己手上最壞的牌要好的牌,就打出自己手上最壞的牌……如此類推,使得勝利的概率不斷增大。


局部淘汰法,可以類比打麻將的過程,不斷更換手上的牌,使得勝利的概率越來越大


這樣,遍歷1次就能得到最后的結果了。總比較次數如何呢?


最好的情況是,如果這1億個數字剛好已經是降序排列,那么前10000個數字就是結果,只需要進行1次最小值的計算(比較次數?1 × 10000),9999萬次最小值的比較(次數向上近似為 n)。


最壞的情況是,如果這1億個數字剛好已經是升序排列,那么直到最后的10000個數字才是最終結果,因此需要進行9999萬次最小值的計算(比較次數?n?× 10000),9999萬次最小值的比較(次數向上近似為?n?


因此,平均的情況是,要算5000萬次最小值(比較次數為?1/2?×?n?× 10000),要算9999萬次最小值比較(次數向上近似為 n?,因此總比較次數近似為 :


1/2?×?n?× 10000 = 5000 × n


總比較次數下降了一半,這個優化有點用。


但是……大家有沒有覺得這個方法還有優化空間?


方法三:最小堆維護法


這個問題嘛……事實上是有的。這個方法能夠大幅度降低總比較次數,稱之為最小堆維護法


第1步:先利用前10000個數字,搭建一個元素個數為1萬的最小堆


有模友可能會問,什么叫做最小堆呢?小智在這里解釋一下:


首先,什么是堆?


關于堆這個概念,我們生活中的理解是東西堆在一起,比如沙堆、泥堆、還有小智的一堆東西


計時沙漏中的小沙堆


在計算機領域中,堆這個概念與生活中的有一點點類似,一般的堆也是上面窄下面寬的結構。堆結構,非常類似圓木堆放的結構,充滿大自然的氣息。


堆結構,可能源自圓木木堆的靈感


堆(heap)是一種基于(tree)的特殊的數據結構。堆有兩種形式,分別是最大堆max heap)和最小堆min heap)。在堆頂的節點則被稱為根節點。


我們關心最小堆就可以了。最小堆中,如果節點 A 是節點 B 的父節點,節點 A 中的鍵值必定小于或者等于節點 B 中的鍵值。根節點是堆的最小值。


以搬磚為例,我們要建一個金字塔,比較穩定的結構是下面重上面輕。最下面的我們放100kg的磚,然后上面可以放輕一點的磚。最小堆的結構也是類似的,位置越往上的節點鍵值越小。每一個節點都有一個鍵值,即所對應的數字,好比每一塊磚頭都對應一個重量,磚頭的重量可以作為磚頭的鍵值。


座結構穩定的小金字塔截面結構


堆的形式有非常多,不過堆的最常見實現形式是二叉堆binary heap),最小二叉堆一般也是被直接簡稱為最小堆,因此我們只需要理解二叉堆即可。我們可以畫一個最小二叉堆的例子出來感受一下:


一個最小堆示例


對圖中的最小堆分析,一共有三層圓圈,稱之為節點,每一個上層的節點都連著下層的兩個節點,而且上層節點的鍵值均比下層的兩個節點的鍵值要小。這個就是最小堆的特征。


我們關注另外一個方面,圖中8個元素的二叉堆里面,堆的高度是3。推而廣之,對于一個有N個元素的二叉堆,其高度為?log2?N


這里還需要問大家一個問題:假設最小堆堆頂的鍵值改變,調整的時間是多少?


這個問題也就是問堆調整時間了。一般對于這種問題,我們都要算最壞情況。假設堆頂新鍵值大于堆里所有的數,那么堆頂這個元素需要調整到堆底,每一次調整都要下降一層,因此調整的次數為堆的高度,即?log2?N


建堆、堆調整以及堆排序的過程展示


解釋得有點長,但是對于問題的理解是有幫助的哦。


我們來繼續做題吧:


第2步:遍歷剩下的數字,與最小堆的根元素鍵值進行對比。如果遍歷到某個數確實大于根元素的鍵值,則替換根元素的鍵值,并進行堆調整


第3步:遍歷完成后,最小堆當中的所有元素對應的數值即為所求。


剛剛說明了堆調整時間,最壞情況下調整時間為?log2?10000。同時要進行9999萬次最小值比較(次數向上近似為?n)。因此上述步驟的比較次數最多為:


n × log2?10000 < 14?× n


總比較次數進一步下降了?5000 ÷ 14 >?350?倍,這個優化確實漂亮。


這個答案小智覺得算是滿意的了。


上面這個題目屬于?Top K?類問題,這類問題的解法,很多時候都可以用這種數據結構進行解答,往往能得到一些不錯的結果。



總結

以上是生活随笔為你收集整理的如何轻松将上亿的数据玩弄于股掌之中?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。