百度的一期筆試題

題目和解答轉自百科中的一篇文章,但是具體答案以及給分標準是否權威,不得而知,答案和下面我的分析僅供參考,出現任何後果金子概不負責哦。


第一題 簡答(30分)



1. 請寫出C++ STL中vector的相關問題。(20分)
(1)在調用成員函數push_back時,其內部的內存分配是如何進行的。(5分)
(2)調用成員函數clear時,內部是如何具體實現的,如果想將其內存釋放,該如何操作。(15分)


答題要點:

(1)當vector發現預先分配的內存不夠用時,會申請一個大小爲當前內存大小兩倍的地址,並把數據拷貝到新地址中。

金子分析:當調用push-back函數時,先查看配用內存是否足夠,如果不夠的話,重新分配一段連續的內存,內存大小爲原來分配的容量的2倍,然後將原來已經存儲的數據複製到新地址,緊接着將要push的數據添在複製數據的後面,最後將原始的分配的內存全部釋放。由於push_back會導致地址空間的改變,所以迭代器指向的內容有改變,這點要注意啦。

(2)在調用clear時,vector並不釋放內存,只是在內部做一個“空”的標記。如果想釋放內存可以參考如下方法:
vector<int> ver(n,0);//需要釋放掉的vector
vector<int>().swap(ver);(這樣便可釋放ver的內存)
金子分析:我怎麼覺得跟STL分析的不太一樣呢???有待查證資料

給分標準:
1、答案正確給出5分。
2、說明clear的實現方法給5分,說明如何具體釋放內存給10分。


2. 請指出下面C語言中foo函數的問題,此函數想統計字符串中的字母a-z分別出現的個數。(10分)
void foo(char a[100], int cnt[256]) {
    memset(cnt, 0, sizeof(cnt)); //sizeof(cnt)在這個時候是指針的大小,32位系統中永遠等於4。此問題給5分
    while (*a != '\0') {
        ++cnt[*a];//因爲有中文,所以這裏*a可能爲負數,會越界。指出問題給5分
        ++a;
    }
    for (char c = 'a'; c <= 'z'; ++c) {
        printf("%c: %d\n", c, cnt[c]);
    }
}
int main() {
    char a[100] = "百度abc";
    int cnt[256] ;
    foo(a, cnt);
    return 0;
}
金子分析:本題考點,當數組做函數形參的時候,數組名就相當於指針,即使數組名後面指定了數組的大小,編譯器也會忽略的。所以想利用memset對數組cnt進行初始化是錯誤的,該初始化的工作應該放到函數體外,在調用函數前執行。中文字符的那個問題我倒是看出來了,越界在答題的時候估計我也可能想到,不過這個爲負數?誰來幫我解答一下,我有點暈。

第二題 算法與程序設計(40分)
1. 假設我們有rand(s, t)函數,可以返回[s,t]之間的隨機小數。請問如何利用該函數在一個半徑爲R的圓內隨機n個點,並給出相應的時間複雜度分析。(15分)


參考答案:
假設一個邊長爲R的正方形把圓包住,那麼可以調用rand(s, t)函數兩次得到正方形內的隨機點(x, y)。留下在圓內的隨機點即可,這樣可以保證隨即概率相等。時間複雜度可以按照圓和正方形的面積比得到:
O(n*(πR^2)/R^2 )=O(n* π)
給分標準:

說出了錯誤的隨機方法可適當給分,給出正確方法給10分,分析了時間複雜度和概率的再給5分。

金子分析:百度很多筆試的題目都跟隨機數有關,碰到隨機數時的時間複雜度分析我就有點暈,下面第2題也一樣,其實都是從《編程珠璣》的題目中衍生出來的。至於本題,我第一次做的時候想到了利用正方形,可以沒有想到直接看點是否在圓內,而是想到按照比例將點向內壓縮。。。另外一個想法是生成兩個隨機數,一個是圓內點與圓心距離(<=R),一個是偏轉角度[0,360],但是概率是否相等和複雜度分析,我就有點暈了。



2. 爲了分析用戶的行爲,系統往往需要存儲用戶的一些query,但是因爲query非常多,所以系統不能夠存下每一條。假設我們的系統每天只能夠存儲m個query,現在需要設計一個算法,對用戶時時請求的query進行隨機選擇m個,請給出一個方案,使得每一個query被抽中的概率儘量相等,也請附加相應的分析。需要注意的是,不到最後一刻你並不知道用戶的總請求量是多少。(25分)


參考答案:
假設每天總共有n個query, 那麼目標是使得每一個query被抽中的概率爲m/n。
系統設計如下:
1. 開一個大小爲m的數組K,前m個query分別依次放入數組K[0..m-1]中。
2. 假設當前的query爲第p個(p>m),隨機一個[0-p)的整數i,如果i<m,則K[i]=query[p],否則棄掉該query。


概率分析:
首先分析最後一個,也就是第n個query。其被抽中的概率=其隨機數i小於m的概率,也就是m/n。再分析第n-1個query的概率。該query放入數組的概率爲m/(n-1)。其沒有被最後一個query替換的概率爲(n-1)/n。所以第n-1個query被抽中的概率爲m/(n-1)*(n-1)/n=m/n。
依次類推,第n-2個query被抽中的概率爲m/(n-2)*(n-2)/(n-1)*(n-1)/n=m/n。
即:每一個query被抽中的概率均爲m/n。


金子分析:這完全就是《編程珠璣》中的一道題啊,從n個數中抽取m個數,保證每個數被抽中的概率相等,我會寫一篇博客來總結幾種方法的。


給分標準:
說出方法即可給分,錯誤的方法給0-5分,正確的方法給10分。
如果有相應的概率分析也加分,方法錯誤分析也錯誤給5分,方法錯誤分析正確給10分,方法正確分析也正確給15分。




第三題 系統設計題(30分)
現在有一個“服務器-客戶端”的實際系統。正常的客戶端每1分鐘最多發送一條請求到服務器,服務器需要做一個異常客戶端行爲的過濾系統。假設服務器在某一個時刻收到了客戶端A的一條請求,那麼1分鐘內的客戶端的任何其他請求都需要被過濾。現在知道每一個客戶端都有一個IPv6的地址可以作爲其ID。客戶端個數太多,以至於無法全部放到單臺服務器的內存hash表中。現在需要簡單設計一套系統,使得支持高效的過濾,可以使用多臺機器,但要求使用的機器越少越好。請把關鍵的設計和思想用圖表和代碼的方式表現出來。


參考答案:
雖然客戶端的ID太多,無法放入到內存中,但是1分鐘內請求服務器的ID卻不會太多。可以根據這個條件進行設計。
申請隊列Q, hash表H。H記錄了每一個請求的到達時間。服務器收到請求之後:
While (隊首的ID請求到達時間超過1分鐘)
出隊,並且清空hash表H中的相關記錄
If 客戶端ID存在於H中then
過濾此請求。
else
將此ID放入Q隊尾
記錄時間到H中,即H[ID]=now()。
給分標準:
簡單分佈式設計可以按照設計情況適當給5-15分。
建立文件索引的方式也給5-15分。
考慮冗餘機制給5分。
此題可以採用單臺機器完成,能發現此特點給10分,給出具體方案再給20分。具體方案可參考代碼風格等等方面酌情給分。




以上爲參考答案,其他符合邏輯的方案可酌情給分


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