百度筆試題1(個人整理)

http://topic.csdn.net/u/20081224/16/23041dbb-b0b9-46c5-9ff7-3a4dede2a6e3.html

1、這是今年百度的一道筆試題。給你1億個ip地址和每個ip訪問的時間(00:00:00= <時間 <=23:59:59,並且已經按照時間排好序了),然後給定一段時間X,定義在X內如果某IP的訪問次數超過Y次,則判定該IP爲攻擊IP。要求輸出所有攻擊IP。只有一組測試用例。第一行輸入IP記錄數(10),時間X(10= <X <=120),次數Y(2= <Y <=100)。輸出按訪問的時間順序輸出,IP重複不再輸出。
輸入示例:(爲了方便,只給出8個,意思意思
)
8 10 2
10.254.82.126 00:00:39
10.85.124.135 00:00:40
10.254.82.126 00:00:44
10.254.82.126 00:00:44
10.1.82.125 00:00:45
10.85.124.135 00:00:48
10.254.82.126 00:00:48
10.254.82.126 00:00:49
輸出示例:

10.254.82.126
10.85.124.135

 

2、偶覺得算法思想可以如下:
輸入隊列比如是

struct ipChain{
  char ip[16];
  char date[16];
}ipArray[100000];
在這個ipArray 維持 2個動態標記: head 初始爲0  tail爲的index ipArray[tail].date - ipArray[head].date <= X 並且 ipArray[tail+1].date - ipArray[head].date > X


tail - head + 1個元素 進行散列,加下每個ip count 大於Y的直接 可以輸出


以後 tail++, 查看先加入的元素是否 使 ipArray[tail].date - ipArray[head].date > x, 大於 head++, 散列表中其count--,一旦爲0,刪除之。然後 將新加入的ipArray[tail] 加入散列表 查看是否 count > Y


這樣的話 算法 應該比 On)差不了多少。

 

3、能把哈希函數告訴嗎?

就是把IP地址散列到10萬的數以內,我是這樣做的

例如:192.168.0.1

hash = (192 × 192 % 100000 + 168 × 168% 100000 + 0 × 0% 100000 + (1 * 1) % 100000) % 100000

有衝突就向後找空位

但是效率不高

求一個效率高的哈希函數

 

4、你自己可以根據 X的大小來選取一個平均的 hash 表長度哈

比如 x = 60(秒)(平均值)

 

1/60/24 * 1 = 7萬左右

 

長度選取 10萬應該挺合理的。

 

hash那就更簡單了  IP 0.0.0.0 正好對應 4* 8(bits) = 32位(1int

寫個函數 int ip_to_int(const char *ip);

將返回的數字 ret % 100000作爲哈希數組索引

 

5、引用 8 huangzhtao 的回覆:

能把哈希函數告訴嗎?

就是把IP地址散列到10萬的數以內,我是這樣做的

例如:192.168.0.1

hash = (192 × 192 % 100000 + 168 × 168% 100000 + 0 × 0% 100000 + (1 * 1) % 100000) % 100000

有衝突就向後找空位

但是效率不高

求一個效率高的哈希函數

 

 

 

還有關於衝突 我覺得你的解決方法 不是很理想,找空位的方法萬一制定x時間內 ip地址超過10萬個呢?所以hash表的 element好好設計下

偶覺得可以

struct hash_element{

 

  const char *ip;

  int count;

  struct hash_element *next;

};

 

ip就放 當前被haship地址字符串的地址,count個數 next指向下一個衝突的地址。

 

這樣  hash_elemnt[100000];的一個hash表應該能搞定 

 

6、引用 13 fisher_047 的回覆:

引用 9 threeleafzerg007 的回覆:

你自己可以根據 X的大小來選取一個平均的 hash 表長度哈

比如 x = 60(秒)(平均值)

 

1/60/24 * 1 = 7萬左右

 

長度選取 10萬應該挺合理的。

 

hash那就更簡單了  IP 0.0.0.0 正好對應 4* 8(bits) = 32位(1int

寫個函數 int ip_to_int(const char *ip);

將返回的數字 ret % 100000作爲哈希數組索引

 

 

我沒太理解9樓的將IP轉換成整數的方法,比如說192.0.0.1轉換後是1920

 

 

 

const char *ip = "127.0.0.1";

int a1,a2,a3,a4,result = 0;

sscanf(ip,"%d.%d.%d.%d",&a1,&a2,&a3,&a4);

result |= a1 < < 24;

result |= a2 < < 16;

result |= a3 < < 8;

result |= a4;

 

7、由於條件上y <100,所以可以用byte數組散列

ip正好可以轉成uint32,這樣需要內存:

(2^32)b=4G Byte!!

如果就這麼回答完畢的話估計是沒分了.

 

可以考慮用鏈地址法來散列

只散列ip的前3.

另外,多用位運算估計就可以了.

 

ip的哈希的問題解決了,然後就可以滾動掃描了

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章