金山的筆試題

2021-06-06 10:04:25 字數 4525 閱讀 8603

乙個金山的筆試題:

有乙個日誌檔案,每行記錄了一次呼叫資訊,其中包括時間和**

ip。每天的記錄數目大約

10億條左右。現在需要:

1)獲取日訪問次數最高的

1000

個**ip

,按照訪問量從高到低排序。

2)獲取連續一周內訪問次數最高的

1000

個**ip

,按照訪問量從高到低排序。

請給出能得到精確(非近似)結果,並且效率盡可能高的計算方法,並給出主要部分偽**。

大資料量的問題,面臨以下幾個問題:一、該

10億條資料中最多有多少條

ip記錄。考慮是否可以一次將記錄讀入記憶體,進行排序

二、ip

記錄過大,無法完全讀入記憶體,則考慮外部排序。

三、考慮演算法的優化,效率問題

四、根據實際的問題,分析考慮如何實現該演算法。

五、是否可已匯入資料庫,使用資料庫操作來實現(其實大部分公司,對日誌的分析,都是匯入的資料庫中進行,並優化資料庫操作,減低資料庫壓力)

l不考慮記憶體空間是否能承受該

10億天記錄

ø堆實現

用堆的方式儲存源位址資訊,每個節點的結構為

typedef unsigned long u32;

struct node;偽碼

:u32 ip;

time time;//以

ip為key建立堆

ret = readline(&ip, &time);

while (ret != eof)

if (istoday(time)) (p->visittoday)++;

is (isthisweek(time)) (p->visitthisweek)++;

ret = readline(&ip, &time);}//

以visittoday

為key

對堆進行重新排序,只要排出前

1000

個即可sortheaptopnwithvisittoday(1000);

printheaptopn(1000);//以

visitthisweek

為key

對堆進行重新排序,只要排出

1000

個即可sortheaptopnwithvisitthisweek(1000);

printheaptopn(1000);

l外部儲存的雜湊

我覺得要得出精確的結果,這個問題要分解成兩個問題

1.統計

ip訪問量日訪問量

2.進行排序

問題1,

確實無法在記憶體裡完成統計,需要借助外部儲存,我暫時能想到的高效的文字檔案結構式是根據

ip進行雜湊,例如

127.0.0.1,

將雜湊到檔案

/127/0/0/ip.dat

這個檔案中,

ip.dat

中將儲存

255個記錄,記錄,均按照

24位二進位制存放,

24位中頭

8位為乙個整形用於存放

ip最後一段,後

16為為長整形用於存放訪問次數,

ip.dat

在建立的時候將直接填滿

24*255

的長度,根據

ip的最後一段進行檔案中的位置定位,這樣就能夠知道這條記錄在

ip.dat

中的文位置,便於改寫(例如

127.0.0.1,1

就在這個檔案中的首位,

127.0.0.129

就在129*24

的位置上)。在統計的過程中,要注意一次要統計一定的記錄數量後,在寫入磁碟,這樣可以降低磁碟讀寫次數,例如,做乙個位圖,

key為

ip,value

為次數,遍歷日誌檔案,當這個點陣圖中的

key超過了

10萬條則寫入磁碟。問題2

,實際上這個問題是如何收集

1000

條值最高的記錄,而不應該是

對所有的記錄進行全部的排序,這樣的話,可以通過乙個大根堆,來進行過濾,每當堆內的節點達到

1001

的時候則將最小的

remove

掉,這樣就將大資料量的排序的問題轉化為小資料量排序,在遍歷了一遍

step1

中的統計結果後,就能夠得出準確的結果了

l演算法設計與分析方面

分成

2個步驟,第乙個步驟是分類統計

如果記憶體足夠,就使用陣列,2的

32次方大小的

uint

陣列,也就是

16gb

。如果記憶體不夠,又不會出現太壞的情況,就用平衡樹。(由於記憶體分配的原因,但如果出現最壞或者很壞的情況,比如

10億個

ip中有

1億個以上不同的

ip,平衡樹實際所需要的記憶體反而比陣列要大)

第二個步驟,就是在第乙個步驟的基礎上進行排序,找出最多的

1000個ip

了最容易想到的就是快速排序,時間複雜度是

o(n*log2n)

。堆排序的效率並不比快速排序高。

但這裡的題目並不是要求我們對所有的

ip進行排序,只是求出前

1000個ip

。所以,對於第二步,有另外一種思路,可以更高效的獲得結果。

這裡做乙個假設,最後

10億個

ip中有

1億個不同的

ip。需要在1億個

ip中找到

1000個ip

。對於快速排序來說複雜度就是

: n*log2n

(n=1

億)。大概等於

26億。

這裡不直接使用快速排序,而是分為三個步驟。

步驟2.1:

ip1,ip2......ip100000000.

現在ip1

與ip2

比較,ip3

與ip4

比較,ip99999999

與ip100000000

比較,得到較大的ip。

假設是ip2,ip4,ip5,ip8.......ip99999999.繼續2

個2個的比較,得到較大的ip。

假設是ip2,ip8......ip99999999

。這樣經過

m次比較(這裡

m=13

),最後得到了大概

1萬個左右的ip。

步驟2.1

複雜度是固定的,並且小於n(

n=1億)

步驟2.2:

這個時候對這

1萬個左右的

ip進行快速排序,複雜度是

x*log2x

(x=1

萬),找出前

1000個ip

。步驟2.3:

那麼剩下

1000個ip

,對於那大概

9000

個左右的

ip,以及被這

9000個ip

淘汰掉的

ip,都可以扔掉了。

我們只需要考慮

1000個ip

以及和被他們淘汰的

ip,也就是

1000*2的m

次方(這裡

m=13

),總共大概是

800萬個ip。

這個時候對

800萬個

ip進行快速排序,複雜度是

y*log2y

(y=800

萬)最終的時間複雜度是步驟

2.1,2.2,2.3

的總和,這裡得到的結果大概是:

1億(步驟1)

+ 13

萬(步驟2)

+ 1億

8千萬(步驟

3),大概是

3億不到。

補充:對於步驟

2,我這裡

m=13

只是隨意給出的乙個方案,對於不同的情況,

m都不一樣,可以通過複雜的計算得到

m的最優值。另外,對於步驟

2.3,實際上也可以遞迴分解為和步驟

2一樣的

3個步驟。

資料量這麼大

,無論是用什麼工具去處理都是不太好處理的

.  我想法

:  1)

它是按時間來進行統計的.所以

,第一步

,我覺得需要把這個十幾億或者是過百億行的檔案拆分了多個檔案

.可以按每小時或者每半小時為乙個檔案

2) 當拆分了多個檔案後

,每個檔案中的

ip進行統計

,並且記錄在永續性介質中

3) 重永續性介質中

,再通過

hash

等方式來進行排序

總結:

到了10

億這個層面上

,常用演算法都是變得相當無力

.我思想是現實有限硬體條件下

,可以對大資料量處理進行拆分,統計

,再重組來處理

.若假象在無限制硬體條件下

,雜湊的方式應該是最快吧

.

金山筆試題(武漢)

4個題 第一題交換兩個變數的值 不能使用臨時變數 第二題,逆序乙個單鏈表 第三題,c 的構造和析構。第四題,三選一 1,字符集的問題 2,com元件的問題 3,跨平台程式設計的問題。解答 第一題 一下還是沒想到,跟乙個同學討論了一下,後面都沒想到。就網上搜了一下。有兩種方法i,不過有一種不是很保險的...

2012 9 26 金山WPS筆試題

今晚的筆試題目不難,所考演算法也不是很難,關鍵在仔細審題和平常的積累 1.有770個節點的完全二叉樹,問葉子節點有多少?重點是葉子節點,不是最下一層的節點數目,陷阱呀 可以計算得出該完全二叉樹的最下面一層的節點數目是259,上一層的節點數目為256,所以,可以得出上一層的葉子節點數目有126,所以結...

一道2005金山筆試題

問題描述 2005年11月金山筆試題。編碼完成下面的處理函式。函式將字串中的字元 移到串的前部分,前面的非 字元後移,但不能改變非 字元的先後順序,函式返回串中字元 的數量。如原始串為 ab cd e 12,處理後為 abcde12,函式並返回值為5。要求使用盡量少的時間和輔助空間 include ...