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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

算法,求1亿个数的中位数

發布時間:2024/4/17 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 算法,求1亿个数的中位数 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

http://bbs.csdn.net/topics/310150772

可以借鑒一下以下方法的:

有1億個浮點數,請找出其中最大的10000個。提示:假設每個浮點數占4個字節,1億個浮點數就要站到相當大的空間,因此不能一次將全部讀入內存進行排序。

  ~~~~~~~~~~~~~

  既然不可以一次讀入內存,?那可以這么試試:

  方法1:?讀出100w個數據,?找出最大的1w個,?如果這100w數據選擇夠理想,?那么以這1w個數據里面最小的為基準,?可以過濾掉1億數據里面99%的數據,?最后就再一次在剩下的100w(1%)里面找出最大的1w個咯~~

  方法2:?分塊,?比如100w一個塊,?找出最大1w個,?一次下來就剩下100w數據需要找出1w個了.(注意消重,這剩下的100w個數據應該是互不相同的。即每找出一個塊里最大的1w個,就應該hash存儲。下一個塊中若出現了已存儲的數據,則不計在此塊的top?1w里,這樣才能保證最終剩下的100w里面尋找top?1w就接近1億里面的top?1w。想想:如果每個塊的top?1w都基本是重復的,不消重的話,最終的結果有可能就少于1w個。)

  對于上面提到的找出100w個數據里面最大的1w個,?說起來比較羅嗦,?還是說說找到第1w個大的數字的方法:

  用快速排序的方法,?分2堆,?如果大的那堆個數N大于1w個,?繼續對大堆快速排序一次分成2堆,?如果大堆個數N小于1w,?就在小的那堆里面快速排序一次,?找第10000-N大的數字;?遞歸以上過程,?就可以找到第1w大的數.?據說也是STL的search_n()的方法;(更好的一種類似的方法是將這些數以5個為一組,每組通過插入排序找出其中位數,再找出其中位數的中位數,依次遞歸,找出最終一個中位數x,然后按照x對序列進行快排,且設x是序列的第k大的數,如果要找的是第i大的數,則比較k與i的關系,如果相等,直接返回x,否則如果k>i,則在小的那堆里面繼續按照這種方式快排,如果k<i,則在大堆里面找第i-k大的數。)

  參考上面的找出第1w大數字,?相信樓主就可以類似的方法找出前1w大數字了

?

真的很感謝有這么多人回答,我的思路就是基本上排序+分塊,
首先1億個數我分成了200塊,每塊50W個,對每個塊進行多路歸并排序(這里不考慮快速排序,相對來說比較低率,不穩定),
排序好后存儲在硬盤文件。
我寫了下,大約是15S左右,
然后在用一個兩維數組記錄這200組數據中的最大和最小值,然后把這200個中位數的平均數求出來,其實沒有別的目的
(目的是為了找一個適合的中位數偏移點,因為這個平均數不一定就是1億個數的,可以叫做先猜一個機率最大的吧)
如果我們這么時候求得的平均數是N
然后就是一個超級土的試探法了,
建立一個偏差數組left[5][200],right[5][200],主要是用來保存N這個數在每個塊里面小于N和大于N?5個的數,用來在后面讀取
1。從文件里一個一個讀取排序好的塊,順便把left,right兩數組填充,找出<=N的數所在的index,最后把這些index相加為sum,看sum是否==1億/2-1
如果相等了,那證明這個數就是中位數了,
2.如果小于
就又從left[0][200]里取最大的一個值,把left[0]排序一下,這樣肯定是最接近N的,然后重復1,但是不改變left,right,看是否是中位數,
如果sum繼續小于,那么繼續2,但是要取left[1][200]最大了,如果sum這時候大于了,證明中位數肯定存在于left[0][200]其中的一個了,
這時候就鎖定了,在left[0]用折半找按上面方法計算sum找中位數,
3。如果大于,和2步驟就是相反的。

這個算法雖然可以找到相關的值,但是在從文件重復讀塊加載到內存方面不知道讀取了多少次,效率肯定不是一般的差,想了一兩天,沒思路了,哎。

?

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 內存只能容納100W個數, 現在有1億數,混序, 然后求這一億個數的中位數, 中位數(就是一個有序數組的中間數字,數組長度為偶數就是兩個,奇數則只有一個) ?? /*****************************************************************************/ /*?this?program?should?find?out?the?median(s)?in?N(logN)/(logB)?no?matter?there /*?is?duplicated?data?or?not. /* /*?with?memory?limitation:?4MB?memory?available. /*?I?would?like?to?express?the?idea?with?code. /*?here?is?just?the?pseudocode?with?out?any?optimization?for?easy?understanding. /*? /*?maybe,?there?is?no?need?to?check?sum?==?N/2?or?N/2+1,?but?this?will?get?the? /*?median(s)?as?soon?as?possible?with?out?more?recursive?invoking. /* /*?sorry?for?any?logical?problem.?please?let?me?know?if?you?found?any. /*****************************************************************************/ ?? ?? int?N?=?100000000;//?total?data?number?is?N int?B?=?1000000;??//?number?of?buckets. int?min,?max; scan?data?from?0?to?N-1?get?min?and?max;?//?O(N); ?? void?find_median(int?num=0,?int?min,?int?max) { ????if(min?==?max)?{ ????????if(N%2)?{ ????????????print?medians?are?min?and?max; ????????} ????????else?print?median?is?min;?//?show?you?the?result ????????return;?//?exit ????} ?? ????/*?count?all?the?data?in?O(N)*/ ????int?m?=?max-min?>?B???(max-min)?/?B?:?1; ????int?cnt[B]?=?{0};?//?count?the?data?read. ????while(!EOF)?{ ????????int?data?=?read_data()-min; ????????if(data?>=?min?&&?data?<=?max)?cnt[data/m]++; ????} ?????? ????int?sum?=?num,?median_1,?median_2,?i?=?0; ????while(sum?<?N/2)?sum?+=?cnt[i++]; ????i--;?//?median?is?in?the?range?of?[i*m,?(i+1)*m-1] ?? ????/*?get?median(s)?when?sum?is?N/2?*/ ????if(sum?==?N/2)?{ ????????if(N%2)?{?//?N?is?even?and?there?are?two?medians. ????????????median_1?=?(i+2)*m-1; ????????????median_2?=?i*m; ????????????while(!EOF)?{ ????????????????int?data?=?read_data()-min; ????????????????if(data/m?==?i)?{ ????????????????????median_2?=?(data?>?median_2???data?:?median_2); ????????????????} ????????????????if(data/m?==?i+1)?{ ????????????????????median_1?=?(data?<?median_1???data?:?median_1); ????????????????} ????????????} ????????????pintf?medians?are?median_1?and?median_2; ????????????return; ????????} ????} ????else?{?//?N?is?an?odd?number?and?there?is?one?median. ????????median_1?=?(i+2)*m-1; ????????while(!EOF)?{ ????????????int?data?=?read_data(); ????????????if(data/m?==?i+1)?median_1?=?(data?<?median_1???data?:?median_1); ????????} ????????print?median?is?median_1; ????????return; ????} ?????? ????/*?get?median(s)?when?sum?is?N/2+1?*/ ????if(sum?==?N/2+1)?{ ????????if(N%2)?{?//?N?is?even?and?there?are?two?medians. ????????????median_1?=?i*m; ????????????median_2?=?i*m; ????????????while(!EOF)?{ ????????????????int?data?=?read_data(); ????????????????if(data/m?==?i)?{ ????????????????????median_1?=?max; ????????????????????median_2?=?(data?>?median_2???data?:?median_2); ????????????????} ????????????} ????????????pintf?medians?are?median_1?and?median_2; ????????????return; ????????} ????} ????else?{ ????????median_2?=?i*m;?//?get?(N/2+1)th?data. ????????while(!EOF)?{ ????????????int?data?=?read_data(); ????????????if(data/m?==?i)?median_2?=?(data?>?median_2???data?:?median_2); ????????} ????????print?median?is?median_2; ????????return; ????} ?? ????/*?recursively?to?find?out?the?median(s)?*/ ????min?=?(i+1)*m-1; ????max?=?i*m; ????//?get?min?and?max?for?next?processing ????while(!EOF)? ????{ ????????int?data?=?read_data()-min; ????????if(data/m?==?i) ????????{ ????????????min?=?(data?<?min???data?:?min); ????????????max?=?(data?>?max???data?:?max); ????????} ????} ????find_median(sum,?min,?max); }

總結

以上是生活随笔為你收集整理的算法,求1亿个数的中位数的全部內容,希望文章能夠幫你解決所遇到的問題。

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