http://blog.csdn.net/Hackbuteer1
2011.10.17百度面試題
1、進程切換需要注意哪些問題。
儲存處理器PC寄存器的值到被中止進程的私人堆棧; 儲存處理器PSW寄存器的值到被中止進程的私人堆棧; 儲存處理器SP寄存器的值到被中止進程的進程式控制制塊;
儲存處理器其他寄存器的值到被中止進程的私人堆棧; 自待運行進程的進程式控制制塊取SP值並存入處理器的寄存器SP; 自待運行進程的私人堆棧恢複處理器各寄存器的值;
自待運行進程的私人堆棧中彈出PSW值並送入處理器的PSW; 自待運行進程的私人堆棧中彈出PC值並送入處理器的PC。
2、輸入一個升序數組,然後在數組中快速尋找兩個數字,其和等於一個給定的值。
這個編程之美上面有這個題目的,很簡單的,用兩個指標一個指向數組前面,一個指向數組的後面,遍曆一遍就可以了。
3、有一個名人和很多平民在一塊,平民都認識這個名人,但是這個名人不認識任何一個平民,任意兩個平民之間是否認識是未知的,請設計一個演算法,快速找個這個人中的那個名人。 已知已經實現了一個函數 bool know(int a,int b) 這個函數返回true的時候,表明a認識b,返回false的時候表明a不認識b。
思路:首先將n個人分為n/2組,每一組有2個人,然後每個組的兩個人調用這個know函數,假設為know(a,b),返回true的時候說明a認識b,則a肯定不是名人,a可以排除掉了,依次類推,每個組都調用這個函數依次,那麼n個人中就有n/2個人被排除掉了,資料規模將為n/2。同理在剩下的n/2個人中在使用這個方法,那麼規模就會將為n/4,這樣所有的遍曆次數為n/2+n/4+n/8+........ 這個一個等比數列,時間複雜度為o(n)。
4、判斷一個自然數是否是某個數的平方。當然不能使用開方運算。
方法1:
遍曆從1到N的數字,求取平方並和N進行比較。
如果平方小於N,則繼續遍曆;如果等於N,則成功退出;如果大於N,則失敗退出。
複雜度為O(n^0.5)。
方法2:
使用二分尋找法,對1到N之間的數字進行判斷。
複雜度為O(log n)。
方法3:
由於
(n+1)^2
=n^2 + 2n + 1,
= ...
= 1 + (2*1 + 1) + (2*2 + 1) + ... + (2*n + 1)
注意到這些項構成了等差數列(每項之間相差2)。
所以我們可以比較 N-1, N - 1 - 3, N - 1 - 3 - 5 ... 和0的關係。
如果大於0,則繼續減;如果等於0,則成功退出;如果小於 0,則失敗退出。
複雜度為O(n^0.5)。不過方法3中利用加減法替換掉了方法1中的乘法,所以速度會更快些。
例如:3^2 = 9 = 1 + 2*1+1 + 2*2+1 = 1 + 3 + 5
4^2 = 16 = 1 + 2*1 + 1 + 2*2+1 + 2*3+1 view plain int square(int n) { int i = 1; n = n - i; while( n > 0 ) { i += 2; n -= i; } if( n == 0 ) //是某個數的平方 return 1; else //不是某個數的平方 return 0; }
百度2011.10.16校園招聘會筆試題
一、演算法設計
1、設rand(s,t)返回[s,t]之間的隨機小數,利用該函數在一個半徑為R的圓內找隨機n個點,並給出時間複雜度分析。
思路:這個使用數學中的極座標來解決,先調用[s1,t1]隨機產生一個數r,歸一化後乘以半徑,得到R*(r-s1)/(t1-s1),然後在調用[s2,t2]隨機產生一個數a,歸一化後得到角度:360*(a-s2)/(t2-s2)
2、為分析使用者行為,系統常需儲存使用者的一些query,但因query非常多,故系統不能全存,設系統每天只存m個query,現設計一個演算法,對使用者請求的query進行隨機播放m個,請給一個方案,使得每個query被抽中的機率相等,並分析之,注意:不到最後一刻,並不知使用者的總請求量。
思路:如果使用者查詢的數量小於m,那麼直接就存起來。如果使用者查詢的數量大於m,假設為m+i,那麼在1-----m+i之間隨機產生一個數,如果選擇的是前面m條查詢進行存取,那麼機率為m/(m+i),如果選擇的是後面i條記錄中的查詢,那麼用這個記錄來替換前面m條查詢記錄的機率為m/(m+i)*(1-1/m)=(m-1)/(m+i),當查詢記錄量很大的時候,m/(m+i)== (m-1)/(m+i),所以每個query被抽中的機率是相等的。
3、C++ STL中vector的相關問題:
(1)、調用push_back時,其內部的記憶體配置是如何進行的。
(2)、調用clear時,內部是如何具體實現的。若想將其記憶體釋放,該如何操作。
vector的工作原理是系統預先分配一塊CAPACITY大小的空間,當插入的資料超過這個空間的時候,這塊空間會讓某種方式擴充,但是你刪除資料的時候,它卻不會縮小。
vector為了防止大量分配連續記憶體的開銷,保持一塊預設的尺寸的記憶體,clear只是清資料了,未清記憶體,因為vector的capacity容量未變化,系統維護一個的預設值。
有什麼方法可以釋放掉vector中佔用的全部記憶體呢?
標準的解決方案如下
template < class T >
void ClearVector( vector< T >& vt )
{
vector< T > vtTemp;
veTemp.swap( vt );
}
事實上,vector根本就不管記憶體,它只是負責向記憶體管理架構acquire/release記憶體,記憶體管理架構如果發現記憶體不夠了,就malloc,但是當vector釋放資源的時候(比如destruct), stl根本就不調用free以減少記憶體,因為記憶體配置在stl的底層:stl假定如果你需要更多的資源就代表你以後也可能需要這麼多資源(你的list, hashmap也是用這些記憶體),所以就沒必要不停地malloc/free。如果是這個邏輯的話這可能是個trade-off
一般的STL記憶體管理器allocator都是用記憶體池來管理記憶體的,所以某個容器申請記憶體或釋放記憶體都只是影響到記憶體池的剩餘記憶體量,而不是真的把記憶體歸還給系統。這樣做一是為了避免記憶體片段,二是提高了記憶體申請和釋放的效率——不用每次都在系統記憶體裡尋找一番。
二、系統設計
正常使用者端每分鐘最多發一個請求至服務端,服務端需做一個異常用戶端行為的過濾系統,設伺服器在某一刻收到用戶端A的一個請求,則1分鐘內的用戶端任何其它請求都需要被過濾,現知每一用戶端都有一個IPv6地址可作為其ID,用戶端個數太多,以至於無法全部放到單台伺服器的記憶體hash表中,現需簡單設計一個系統,使用支援高效的過濾,可使用多台機器,但要求使用的機器越少越好,請將關鍵的設計和思想用圖表和代碼錶現出來。
三、求一個全排列函數:
如p([1,2,3])輸出:
[123]、[132]、[213]、[231]、[321]、[323]
求一個組合函數
如p([1,2,3])輸出:
[1]、[2]、[3]、[1,2]、[2,3]、[1,3]、[1,2,3]
這兩問可以用虛擬碼。
網易遊戲2011.10.15校園招聘會筆試題
1、對於一個記憶體位址是32位、記憶體頁是8KB的系統。0X0005F123這個地址的頁號與頁內位移分別是多少。
2、如果X大於0並小於65536,用移位法計算X乘以255的值為: (X<<8)-X
X<<8-X是不對的,因為移位元運算符的優先順序沒有減號的優先順序高,首先計算8-X為0,X左移0位還是8。
3、一個包含n個節點的四叉樹,每個節點都有四個指向孩子節點的指標,這4n個指標中有 3n+1 個null 指標。
4、以下兩個語句的區別是:第一個動態申請的空間裡面的值是隨機值,第二個進行了初始化,裡面的值為0 view plain int *p1 = new int[10]; int *p2 = new int[10]();
5、電腦在記憶體中儲存資料時使用了大、小端模式,請分別寫出A=0X123456在不同情況下的首位元組是,大端模式:0X12 小端模式:0X56 X86結構的電腦使用 小端 模式。
一般來說,大部分使用者的作業系統(如windows, FreeBsd,Linux)是小端模式的。少部分,如MAC OS,是大端模式 的。
6、在遊戲設計中,經常會根據不同的遊戲狀態調用不同的函數,我們可以通過函數指標來實現這一功能,請聲明一個參數為int *,傳回值為int的函數指標:
int (*fun)(int *)
7、下面程式運行後的結果為:to test something view plain char str[] = "glad to test something";