數學&機率題&智力題&算法題 總結

組合數公式:算法

1. C(n,m)=C(n,n-m)數組

2. C(n,m)=C(n-1,m-1)+C(n-1,m) 楊輝三角spa

等差數列:設計

通項公式:an=a1+(n-1)dcode

前n項和:s=n*a1+n(n-1)/2*dblog

等比數列:排序

通項公式:an=a1*q^(n-1)隊列

前n項目和: s=a1*(1-q^n)/(1-q)遊戲

直線公式:內存

y=kx+b   k=(y2-y1)/(x2-x1)   b=y1-x1*(y2-y1)/(x2-x1)

兩直線平行k1=k2 兩直線垂直 k1*k2=-1

 

1. 給一條長度爲1的線段,在線段上選取兩個點將其分紅3段,求這三段能拼成三角形的機率?

根據三角形兩邊之和大於第三邊,兩邊之差小於第三邊,假設其中一段距離左端點的距離爲x,另外一段爲y,令y>x,那麼三段的長度分別爲x, y-x, 1-y

根據兩邊之和大於第三邊有:y > 1/2 , y-x < 1/2 , x < 1/2, y-x > 0,這幾個條件能夠肯定一個三角形,面積是1/8,這表明x和y能構成三角形的取值範圍。

對於線段的切割,有 0<x<y<1, 也就是0<x<1, 0<y<1, x<y組成三角形的面積是1/2,那麼1/8/(1/2)=1/4即爲能組成三角形的機率。

 

2. 將54張撲克牌均分紅3份,其中大小王在一份裏面的機率是多少?

首先將54張牌均分紅3份的分法有:M = C(54, 18)*C(36, 18)*C(18, 18)

大小王在一張牌中的分法有:N = C(3, 1)*C(52, 16)*C(36, 18)*C(18, 18)

那麼N / M即爲所求。

 

3. 有兩個盒子,50個紅球和50個黑球,如今設計一種分配方案,使得隨機選擇一個盒子,而後隨機選擇一個球,這個球是紅球的最大機率是多少?

分配方案:將一個盒子裏放一個紅球,而後其餘全部球都放到另外一個盒子裏面。

機率:1/2 * 1 + 1/2 * 49/99 =  74.7%

 

4. 將一個數組均勻打亂的算法?

令當前數組長度爲n,在裏面隨機選擇一個數,將其與最後一個數交換,而後再對前n-1個數作相同操做。

 

5. 利用異或進行兩數交換

a = a^b

b = a^b

a = a^b

分析:先令a=a^b,那麼b=a^b=(a^b)^b=a,a=a^b=(a^b)^a=b

 

6. 不用比較符求出a,b的最大值

max=(abs(a+b)+abs(a-b))/2

分析:if a > b 有 max = (a+b+a-b)/2 = a

        if a < b 有 max = (a+b+b-a)/2 = b

 

7. 不用加減乘除運算符求兩個數的和

while(b) {

  sum = a^b;

  carry = (a&b)<<1;

  a = sum;

  b = carry;

}

return a;

分析:a^b的意思是a和b在二進制下相加,可是不考慮進位,a&b在二進制下爲1的位表示相加須要進位的地方,因此須要向左移一位,而後只要進位不爲0,就須要再次和上一次不考慮進位的和用一樣的方法進行相加。

 

8. X>=5,X和X+2爲素數,證實X+1是6的倍數

首先任意三個連續的天然數都有一個能夠被3整除。

證實:對於n-1, n, n+1

假設n%3=0

假設n%3=1有(n-1)%3=0

假設n%3=2有(n+1)%3=0

得證。

所以因爲X和X+2都是素數,那麼X+1必定是3的倍數,因爲X>=5且X和X+2都是素數那麼它們必定是奇數因此X+1必定是偶數,X+1含有因子2和因子3因此必定能被6整除。

 

9. 隨即洗牌算法及其證實

在1~n隨機選一個數與a[n]交換,再從1~n-1隨機選一個數和a[n-1]交換,以此類推。這樣作能夠作到均勻洗牌,也就是1~n的全排列能夠等機率的均勻獲得。

證實:首先從n個數中隨機選共有n種可能狀況,而後在n-1個數中隨機選共有n-1種可能狀況,那麼能夠得到的狀況有n*(n-1)*(n-2)*...*1種,至關於全排列,也就是全排列中的全部狀況均可以等機率的獲得。

 

10. 從海量數據(不能讀入內存中)中找中位數,數據都是32位的

解法一:採用分段讀入的方法,假設每次讀入n個數,用一個長度爲n的優先隊列進行維護,這樣掃一遍海量數據,就能夠的到數據中前n大的數,把這n個數去掉,假設海量數據有N個,那麼下次就只讀入剩下的N-n個數,再找到的就是n+1~2n大的數,以此類推,直到找到第N/2個數。時間按複雜度是O(N/2/n*Nlogn)。

解法二:從32位入手,將每一個數據按照二進制分紅先後兩部分,分別爲16位長度,先按照前16位,分紅2^16個區間,掃一遍海量數據,統計每一個區間一共有多少個數,而後能夠肯定中位數所在區間,以後就是在這個區間找第k個數,用後16位,將中位數所在的那個前16位區間分紅2^16份,統計每一個區間有多少個數,就能夠肯定中位數是哪一個了,時間複雜度是O(n)。

 

11. 三門問題

三扇門,一扇後面有車,另外兩扇後面是羊,如今你選了一扇後,主持人打開一扇發現是羊,問你換不換,換了是車的機率是多少?不換是車的機率是多少?

用貝葉斯公式解釋一下:

P(你當前選擇的這扇門是車|主持人選擇的一扇門是羊) = P(你選擇的這扇門是車&主持人選擇的一扇門是羊) / P(主持人選擇的一扇門是羊)

                                                                    = P(主持人選擇的一扇門是羊|你選擇的這扇門是車) * P(你選擇的這扇門是車) / P(主持人選擇的一扇門是羊)

                                                                    = (1 * 1 / 3) / 1

                                                                    = 1 / 3

因此更換另外一扇門是車的機率爲2 / 3, 不更換當前這扇門是車的機率是1 / 3。

 

12. 燒香問題

兩柱香,燒完一柱香所用時間都是1小時,找出一種能夠判斷15分鐘的切割方法

先點燃香1的一端,同時點燃香2的兩端,當香2燃盡後,過了半小時,香1還剩一半,這時同時點燃香1的兩端就能夠在15分鐘內燃盡。

 

13. 燈管問題

房間裏有三盞燈分別由三個開關控制,只能進房間一次,須要找出哪一個開關控制哪盞燈

先打開一盞燈一段時間,而後關閉它,打開另外一盞燈,進入房間,能夠肯定當前開關控制着哪盞燈,而後摸一下,熱的那個就是以前那盞燈,剩下一盞燈對應沒打開過的那個開關。

 

14. 盲人分襪子

兩個盲人,每人都買了黑白兩對襪子,總共8只,可是他們把襪子混到了一塊兒,如今要求找出一種方案,使得每人都有一對黑襪子和一對白襪子

每一個人分別在一對襪子裏拿一隻就能夠了。

 

15. 蓄水池採樣

問題1. 構造一個隨機數生成器,使得若是其生成數範圍在1~n則每一個數被選中的機率都是1/n,好比範圍是1~2那麼獲得1和2的機率都是1/2,範圍是1~3則獲得1,2,3點機率都是1/3。

構造方法是:首先令num=1,而後用1/2的機率去決定是否用2替換num,也就是令num=2,而後再用1/3的機率決定是否用3替換2,依此類推,對於第n個數n用1/n的機率決定是否用n去替換num。這樣下來,n個數替換結束後,num=1~n中任意數字的機率都是1/n。

證實: 開始只有1,那麼1被選中的機率P(1)=1,以後添加了2,2被選中的機率是P(2)=1/2,此時1還能被選中的機率P(1最終保留下來)=P(1被選中)*P(2沒被選中的機率)=1*(1-1/2)=1/2,以後又添加了3,那麼若是已經用2替換了1,此時2不被替換掉機率是P(2最終保留下來)=P(2被選中)*P(3沒被選中的機率)=1/2*(1-1/3)=1/3,也就是說範圍1~3內,最終生成了2的機率是1/3,再來看1,若是1一直沒被替換掉,也就是P(1最終保留下來)=P(1被選中)*P(2沒被選中)*P(3沒被選中)=1*(1-1/2)*(1-1/3)=1*1/2*2/3=1/3,也就是說在1~3的範圍內,最終生成了1點機率也是1/3。

那麼對於n個數最終生成第m個數的狀況,有:

P(m最終保留下來)=P(m被選中)*P(m+1沒被選中)*P(m+2沒被選中)*...*P(n沒被選中)

                        =1/m*(1-1/(m+1))*(1-1/(m+2))*...*(1-1/n)

                        =1/m*m/(m+1)*(m+1)/(m+2)*...*(n-1)/n

                        =1/n

也就是說n個數中,每一個數都是等機率被選中的,得證。

問題2. 在1~n的範圍內選出k個數,保證1~n每一個數被選中的機率相等。

構造方法是:先保留1~k,而後增長一個數k+1,拿他替換1~k中的數字的機率是k/k+1,替換必須是等機率的1/k,對於第n個數,拿他替換1~k中的數字的機率是k/n,這樣能夠保證範圍在1~n的全部數中每一個數被選到這k個數中的機率都是k/n。至關於把上個問題的1變成了k。

證實:首先只有k個數的時候它們被選中的機率是1,那麼第k+1個數選進來,這k個數中的某一個ki不被替換的機率是

P(ki保留下來)=P(ki被選中)*[P(k+1被選中)*P(k+1沒有替換ki)+P(k+1沒被選中)]=1*[k/(k+1)*(k-1)/k+1/(k+1)]=k/(k+1)

對於m保留到最後的機率爲

P(m保留到最後)=P(m被選中)*[P(m+1被選中)*P(m+1沒替換m)+P(m+1沒被選中)]*[P(m+2被選中)*P(m+2沒替換m)+P(m+2沒被選中)]*...*[P(n被選中)*P(n沒替換m)+P(n沒被選中)]

                     =k/m*[k/(m+1)*(k-1)/k+(m+1-k)/(m+1)]*[k/(m+2)*(k-1)/k+(m+2-k)/(m+2)]*...*[k/n*(k-1)/k+(n-k)/n]

                     =k/m*m/(m+1)*(m+1)/(m+2)*...*(n-1)/n

                     =k/n

也就是說n中的任意一個數被選到k個數裏的機率都是k/n,得證。

應用1. 給個很長的鏈表,不知道具體有多少節點,如今只容許遍歷鏈表一次,讓從鏈表中選擇k個節點,而且鏈表中節點都是等機率被選中的。

先遍歷前k個節點,而後從第k+1個節點開始,每增長一個節點,若是這個節點是第i個,都保證它有k/i的機率被選中,而且以1/k的機率去替換k個節點中的一個,當遍歷完鏈表以後k個節點即爲知足等機率條件被選取的節點。

 

16. 用隨機數生成器rand5()去構造一個隨機數生成器rand7()

用兩個隨機數生成器rand5()能夠均勻生成25個五進制數,而後將這些五進制轉換爲10進制是6~30,減去5獲得1~25,而後將22~25捨棄,也就是獲得這幾個數就從新取,將1~21三個一組分紅7組,也就是模7同餘的數放到一組。

相似的還能夠用rand7去組合rand10:用兩個rand7生成49個數,而後去掉9個,4個一組。

rand2和rand5去組合rand10:rand2=0時返回rand5,rand2=1時返回rand5+5。

rand2和rand7去組合rand10:rand2=0時返回rand7,rand2=1時返回rand7+7去掉最後四個數。

 

17. 幼兒園有4名男孩和若干名女孩,如今加入一名兒童,性別隨機,而後隨機挑出一名兒童是男孩,問加入的那名兒童是女孩的機率。

運用貝葉斯公式解決:A表示挑出了一名男孩  B1表示加入了一名男孩  B2表示加入了一名女孩

如今求 P(B2|A)=P(B2A)/P(A)=P(A|B2)P(B2)/[P(A|B1)P(B1)+P(A|B2)P(B2)],由於加入兒童的性別是隨機的,所以,P(B1)=P(B2)=1/2,假設開始有N名女孩,那麼上式

P(B2|A)=P(A|B2)/(P(A|B1)+P(A|B2))=4/(N+1)/[5/(N+1)+4/(N+1)]=4/9。

 

18. 擲骰子,正面朝上的數字有多大就給多少錢,問最多願意花多少錢去玩這個遊戲?

計算收益的數學指望,骰子六個面,每一個面朝上的機率是1/6,那麼受益的指望是 1*1/6+2*1/6+3*1/6+4*1/6+5*1/6+6*1/6=3.5 因此最多花3.5元去玩。

子問題:若是能擲兩次,第二次能夠選擇擲或者不擲,而且若是第二次擲了,那麼受益只能按照第二次的給,問願意花多少錢去玩?

已知擲一次指望收益是3.5元,也就是說第二次指望受益是3.5元,因此若是第一次擲出了4 5 6的話,第二次確定不擲了,不然仍是要擲一發試試的,第一次擲出4 5 6的機率是1/2,因此選擇擲第二次的機率也是1/2,第一次若是擲出了1 2 3的話,受益應該按照第二次的算,也就是3.5,第一次若是擲出了4 5 6的話,收益按照第一次算也就是4*1/3+5*1/3+6*1/3=5,那麼最終指望受益是5*1/2+3.5*1/2=4.25

 

19. 桶裏面有M個白球,每次從桶中取一個球,不論是白球仍是紅球都染紅而後再放回去,問將桶中全部球都染紅的指望次數是多少?

令E[i]表示桶裏已經有i個紅球,將剩下的球都染紅的指望次數,那麼有E[i]=(i/M)*E[i]+(1-i/M)*E[i+1]+1, 化簡後有E[i]=E[i+1]+M/(M-i)

有P[M]=0,能夠進行遞推P[M-1]=P[M]+M/1=M, P[M-2]=P[M-1]+M/2=M+M/2, P[M-3]=P[M-2]+M/3=M+M/2+M/3, ... , P[0]=P[1]+1=1+M/(M-1)+...+M/3+M/2+M

 

20. 無窮多隻兔子,體重不一,從裏面選出10只,挑出重量最大的A,而後再選20只,挑出其中重量最大的B,問A比B大的機率是多少?

至關於一共挑出來30只兔子,分紅兩堆,一堆10只,一堆20只,問重量最大的兔子在第一堆中的機率是多少,C(10,1) / C(30,1) = 1/3

 

21. 擲骰子直到出現6爲止,問出現6的指望次數是多少?

設擲出6的指望次數爲E,那麼當前成功的機率是1/6,失敗的機率是5/6,成功的話擲1次,失敗的話擲1次後還要再擲E次,因此指望遞推公式是

E=1/6*1+5/6*(1+E),E=6

 

22. 一把寶劍,目前是1級,每往上升一級須要一個寶石,升級成功率是50%,等級小於5的時候,失敗不會降級,等級大於5的時候,失敗會降一級,問將寶劍升到9級至少須要寶石的指望數量。

設E[i]表示從等級i-1升到i的指望寶石數量,那麼對於i<=5,有 E[i]=1/2*1+1/2*(1+E[i]),有E[i]=2,對於i>5的狀況有 E[i]=1/2*1+1/2*(1+E[i-1]+E[i]),表示若是成功花費一塊寶石,若是失敗,首先須要花費一塊寶石,而後降一級到i-2因此須要先升到i-1花費E[i-1]塊寶石,而後再升到i須要E[i]塊寶石,獲得E[i]=E[i-1]+2,那麼有E[2]=E[3]=E[4]=E[5]=2,

E[6]=4, E[7]=6, E[8]=8, E[9]=10,從1級升到9級須要E[2]+E[3]+...E[9]=36塊寶石。

 

23. 兩我的輪流拋硬幣,先拋到正面者能夠吃到蘋果,問先手吃到蘋果的機率是?

P(先手吃到蘋果的機率)=P(先手第一次拋出正面)+P(先手第二次拋出正面)+P(先手第三次拋出正面)+...+P(先手第n次拋出正面) ,其中n是趨於無窮大的。

                             =P(先手第一次拋出正面)+P(先手第一次沒拋出正面)*P(後手第一次沒拋出正面)*P(先手第二次拋出正面)+...+P(先手第一次沒拋出正面)*P(後手第一次沒拋出正面)*...*P(先手第n-1次沒拋出正面)*P(後手第n-1次沒拋出正面)*P(先手第n次拋出正面)

                             =1/2+1/2*1/2*1/2+...+1/2*1/2*...*1/2+...

                             =1/2+1/2^3+1/2^5+...+1/2^n+...

等比數列的前n項和,s=a1(1-q^n)/(1-q)其中n是趨於無窮大的,那麼n趨於無窮時s=1/2*(1-1/4^n)/(1-1/4)=2/3。

 

24. 一對夫婦,前後生了兩個孩子,其中一個是女孩,問另外一個是男孩的機率是多少?

由於題目說了是"前後",因此須要討論前後順序,總共四種可能:(男男),(女女),(男女),(女男),其中一個是女孩,那麼總共只有其中三種狀況,這三種狀況中一女一男總共兩種狀況,所以答案是2/3。

若是不分前後順序的話,那總共只有(女女)和(男女)兩種狀況,答案就是1/2了。

 

25. 一個國家裏的每一個家庭都只想要男孩,他們會一直生,直到生出一個男孩爲止,問這個國家的男女比例是多少?

單看每一個家庭,男孩個數的指望E1=1,由於生出一個男孩後就不會再生。女孩的指望個數是E2,生女孩的狀況有 (男) (女男) (女女男) (女女女男) ... (女女...女男),

E2=1/2*0+1/2*1/2*1+1/2*1/2*1/2*2+...+(n-1)*(1/2)^n+...

    =(1/2)^2+2*(1/2)^3+3*(1/2)^4+...+(n-1)*(1/2)^n+...

2E2=1/2+2*(1/2)^2+3*(1/2)^3+...+n*(1/2)^n+...

2E2-E2=E2=1/2+(1/2)^2+(1/2)^3+...+(1/2)^n+...

等比數列的前n項和是E2=(1/2)*[1-(1/2)^n]/(1-1/2)=1

E1=E2=1男女孩指望個數都是1,因此比例是1:1

 

26. 平均要取多少次(0,1)以內的隨機數才能讓其和超過1?

e次,e是天然對數的底。

 

27. 兩我的在一個圓桌上放硬幣,直到擺不下就算輸,問先手的必勝策略?

先手將硬幣放桌子中間,而後後手放在哪一個位置,先手就放在其對稱的位置。

 

28. 一個矩形蛋糕,中間有個矩形空洞,矩形空洞並非位於蛋糕中心,如何一刀將蛋糕分紅面積相同的兩份?

取蛋糕中心點和空洞中心點的連線,而後沿着這條線切割,確定能夠將矩形蛋糕和空洞平分,那麼它倆面積的差確定也是平分的。

 

29. N*M的巧克力,每次只能將一塊掰成兩塊,問掰成N*M的小塊至少須要掰多少次?

N*M-1次,由於每掰一次只能增長一塊巧克力。或者這樣作,先掰成M塊,須要M-1次,再將這M塊掰成N*M塊,須要M*(N-1)次,總共M*N-1次。

 

30. N個數,每一個數都不超過N-1(至少有一個數重複了),如今告訴你有一個數是重複的,如何找出這個數?若是每一個數都不超過N+1,每一個數都不重複,問1~N+1少了哪一個?

1. 用這N個數的和減去1~N-1的和。

2. 用1~N+1的和減去這N個數的和。

 

31. 判斷一個數是否是2的冪

一個數是2的冪,那麼二進制表達式中最高位是1,其餘位全是0,因此直接判斷b&(b-1)是否爲0就能夠了。

 

33. A和B分別在兩座島上,B有病,A有藥,C有船,船上有箱子,箱子要是不上鎖東西會被偷走,A和B各自有把鎖,問A如何將藥運給B?

首先A把藥放到箱子裏面,而後上鎖,運到B這裏後B上本身的鎖,再運回A,A將本身的鎖打開,再運回B,B打開本身的鎖就好了。

 

34. 兩種藥A和B,天天分別吃一粒A和B,如今打開藥瓶A,倒出一片在手上,而後打開藥瓶B不當心倒出了兩片在手上,問如何保證不浪費藥片的前提下正確服藥?

再倒出一片A藥片,而後將每片藥都等分,如今有四堆,分兩天吃,天天都在每堆裏面選擇一半,能夠組成A+B。

 

35. 如何用一個天平、7g和2g的砝碼稱三次將140g砝碼分紅50g和90g?

第一次將140g分紅70g和70g

第二次一邊放9g一邊放70g,而後獲得61g

第三次一邊放9g一邊放61g,獲得50g。。。

 

36. 三筐水果,分別是蘋果、梨、蘋果和梨混合,每一個筐的標籤都是錯的,如今要求從一個筐子裏面選出一個水果,而後判斷出每一個筐子的實際狀況。

拿貼着混合標籤的筐子裏面的一個水果,若是是蘋果,那麼這個筐子必定全是蘋果,而後另外兩個筐子不是梨就是混合,貼着梨的確定不是梨,確定是混合,那麼貼着混合的確定是梨。若是第一次拿的是梨也同理。

 

37. 25匹馬,速度都不一樣,一共5個賽道,不能計時,一次只能知道五匹馬的速度快慢,問至少須要多少場比賽才能分出前三名?

把這25匹馬分紅5組,賽五場,而後每場最快的馬拿出來再賽一場,就知道最快的馬了,根據最後這場的前三名,找出它們以前所在的組,由於第四第五名的馬所在的組確定不會有哪匹馬能成爲二、3名,對於最後一輪前三名所在的組,第一名所在的組中速度第二、3快的有可能成爲全部馬中二、3快的,第二名所在的組中速度第一、2快的有可能成爲全部馬中第二、3快的,而後第三名中速度最快的有可能成爲全部馬中第3快的。這樣一來這五匹馬再賽一輪,取前兩名就是全部馬中第二、3快的。總共須要比7次。

 

38. 給10億個數排序

使用位圖bitmap,10億個數有10^9,假設裏面最大的數是10^9,那麼分紅20組,每組5*10^7個,而後對於每一個數字num,將bitset第num位置爲1,總共遍歷20次就能完成排序。

bitset<10000000> bitmap將佔用10000000bit的內存,也就是1250000Byte。

下面的代碼對10000000個數據進行排序,分兩次讀入,第一次讀入[0,5000000)範圍內的數據,第二次讀入[5000000,1000000)範圍內的數據。排序思想和技術排序同樣。

#include <cstdio>
#include <bitset>
#include <time.h>
#include <stdlib.h>
using namespace std;

const int max_each_scan = 5000000;  // 每次讀入的數字範圍

int main()
{
    clock_t begin = clock();   // 開始計時
    bitset<max_each_scan> bitmap;   // 位圖使用bitset
    
    FILE *fp_unsort_file = fopen("unsort.txt", "r");
    int num;
    while(fscanf(fp_unsort_file, "%d ", &num)!=EOF)
    {
        if(num < max_each_scan) bitmap.set(num, 1);   // 將第一組數據存入位圖中
    }

    FILE *fp_sort_file = fopen("sort.txt", "w");
    for(int i=0;i<max_each_scan;++i)
    {
        if(bitmap[i]) fprintf(fp_sort_file, "%d ", i);
    }
    
    int result=fseek(fp_unsort_file, 0, SEEK_SET);   // 將文件光標移動到文件的開始
    if(result) printf("fseek failed!\n");
    else
    {
        bitmap.reset();
        while(fscanf(fp_unsort_file, "%d ", &num)!=EOF)
        {
                        // 將第二組數據存入位圖中
            if(num >= max_each_scan && num < (max_each_scan<<1))
            {
                num -= max_each_scan;
                bitmap.set(num,1);
            }
        }
        for(int i=0;i<max_each_scan;++i)
        {
            if(bitmap[i]) fprintf(fp_sort_file, "%d ", i + max_each_scan);
        }
    }
    clock_t end=clock();   // 記錄程序運行結束的時間
    printf("Time cost is %ds\n",(end-begin)/CLOCKS_PER_SEC);
    fclose(fp_sort_file);
    fclose(fp_unsort_file);
    return 0;
}

 

39. 在10億條數據中找出重複出現次數最多的前n條

使用位圖的思想,將10^9的數據分紅1000組,每組10^6個,而後對這10^9條數據進行1000次遍歷,注意無法一次存到內存中,只能從文件中每次讀取一個,而後判斷當前數據是否在[0,10^6), [10^6,2*10^6), ... , [999*10^6,10^9)範圍內,對於每一組範圍都經過偏移將數據映射到[0,10^6)內部,統計其出現次數,而後使用優先隊列維護n個元素,用每一組範圍的統計結果來更新優先隊列便可。

若是指明數據時IP地址的話,因爲IP地址是32位的,所以總共可能有2^32種狀況存在,將其分爲2^10組便可。

示例代碼:

#include <cstdio>
#include <queue>
#include <utility>
#include <string.h>
using namespace std;

int times[10000001];
const int max_each_scan = 10000000;
typedef pair<int,int> P;
priority_queue< P, vector<P>, greater<P> > q;

int main()
{
    FILE *unsort_file = fopen("data.txt", "r");
    for(int i=1;i<=10;++i)
    {
        int num;
        memset(times, 0, sizeof(times));
        while(fscanf(unsort_file, "%d", &num)==1)
        {
            if(max_each_scan*(i-1)<num && num<=max_each_scan*i) ++times[num-(i-1)*max_each_scan];
        }
        for(int j=1;j<=max_each_scan;++j) 
        {
            if(times[j])
            {
                q.push(P(times[j],j+(i-1)*max_each_scan));
                if(q.size() == 11) q.pop();
            }    
        }
        if(fseek(unsort_file, 0, SEEK_SET))
        {
            printf("fseek failed\n");
            return -1;
        }
    }
    while(!q.empty()) {printf("%d\n",q.top().second);q.pop();}
    return 0;
}

 

40. 要求在10億個32位整數中找到第k大的數,10億個數太多沒發存到內存中,只能存到文件中。兩種解法,一是能夠將32位數分紅兩段,開闢一個2^16大小的數組,而後遍歷全部數據,將每一個數據高16位對應數組每一個元素,統計每一個區間的元素個數,而後判斷第k大的數在哪一個區間中,這樣就肯定了這個數據的高16位,以後再遍歷一遍,統計高16位知足條件的數中低16位落到指定區間的個數,而後就能夠判斷第k大的數是哪一個了。

還有一種解法是用位圖的思想,將數據分紅2^10個區間,每一個區間長度都是2^22,使用優先隊列記錄每一個區間前k大的數便可。

相關文章
相關標籤/搜索