第一道題:C++/Java/Objective-C/C#語言是如何體現面向對象思想的。
不管什么面向對象語言,其面向對象思想就是通過面向對象特點:繼承,封裝,多態來實現面向對象設計(好像還有個抽象性,這里就不說了)。
在Java中:
繼承性 Java通過繼承實現代碼復用。繼承而得到的類稱為子類,被繼承的類稱為父類。子類不能繼承父類中訪問權限為private的成員變量和方法。子類可以重寫父類的方法,及命名與父類同名的成員變量。但Java不支持多重繼承,即一個類從多個超類派生的能力。
封裝性 java語言中,對象就是對一組變量和相關方法的封裝,其中變量表明了對象的狀態,方法表明了對象具有的行為。通過對象的封裝,實現了模塊化和信息隱藏。通過對類的成員施以一定的訪問權限,實現了類中成員的信息隱藏。Java有四個不同的限定詞:public,private,protected,default。
多態性 多態性體現在兩個方面:由方法重載實現的靜態多態性(編譯時多態)和方法重寫實現的動態多態性(運行時多態)。
對於C++來說,本人了解不多,我覺得它與Java在面向對象語法和概念上有很多相似的地方,然而Java是一種完全面向對象的語言,所有的東西都是在類中的,而C++中,全局變量、結構、枚舉、聯合等一些列源於C的概念仍然存在;同時其main方法也在所有的類之外。
至於C#和Objective-C本人沒怎么接觸,個人感覺主要思想都差不多,只是一些語法上的區別,重點在面向對象這四個字上,而不在與是什么語言。
第一題就到這兒,本人應屆生渣渣,筆試就是為了攢人品查漏補缺,哪里不對希望大神指正。
第二道題:TCP協議主動連接和主動斷開的過程。
若A為主動打開鏈接方,B為被動打開鏈接方。
主動連接過程:
B的TCP服務進程先創建傳輸控制塊TCB,准備接受A的連接請求,然后B處於收聽狀態(Listen);
A的TCP進程也是先創建傳輸控制塊TCB,然后向B發出連接請求報文段,這時首部中的同步位SYN=1,同時選擇一個初始序號seq=x。A進入同步已發送狀態(SYN-Sent)。
B收到連接請求報文后,如果同意連接,則向A發送確認。在確認報文中把SYN和ACK都置1,確認號ack=x+1,同時也為自己選擇一個初始序號seq=y。B進入同步收到狀態(SYN-Rcvd)。
A收到B的確認后,還要向B給出確認。確認報文段的ACK置1,確認號ack=y+1,seq=x+1,這時連接建立。A進入已建立連接狀態(Established)。
若B收到A的確認,B也進入已建立連接狀態(Established)。
主動斷開過程:
A發送連接釋放報文,停止發送數據,報文首部FIN置1,序號seq=u,A進入終止等待1狀態(FIN-Wait-1),等待B的確認。
B收到連接釋放報文段后發出確認,確認號ack=u+1;seq=v,B進入關閉等待狀態(CLOSE-Wait)。這之后B可能還會向A發送數據,但A不會向B發送數據。
A收到B的確認,進入終止等待2狀態(FIN-Wait-2),等待B發出的連接釋放報文。
若B已經沒有向A發送數據,這時B發出連接釋放報文使FIN=1,序號seq=w,確認號ack=u+1,B進入最后確認狀態(LAST-ACK),等待A的確認。
A收到B的連接釋放報文后必須發出確認,ACK置1,確認號ack=w+1,序號seq=u+1,進入時間等待狀態(Time-Wait),A必須等待時間等待計數器設置的2MSL(最長報文段壽命)后A才進入到關閉(Close)狀態。這時連接斷開。
第三道題:const含義是什么,使用const有什么好處,同時解釋下面五個表達式的含義。
const int a;
int *const a;
int const a;
const int *a;
int const *a const;
我覺得應該是在C或者C++中理解它,const是一個C語言的關鍵字,它限定一個變量不允許被改變。使用const在一定程度上可以提高程序的安全性和可靠性,另外,在觀看別人代碼的時候,清晰理解const所起的作用,對理解對方的程序也有一些幫助。
對於這五條語句我也是有點暈直接百度上來:
const int a; int const a; 這兩個寫法是等同的,表示a是一個int常量。
const int *a; 表示a是一個指針,可以任意指向int常量或者int變量,它總是把它所指向的目標當作一個int常量。也可以寫成int const* a;含義相同。
int * const a; 表示a是一個指針常量,初始化的時候必須固定指向一個int變量,之后就不能再指向別的地方了。
int const * a const;這個寫法沒有,倒是可以寫成int const * const a;表示a是一個指針常量,初始化的時候必須固定指向一個int常量或者int變量,之后就不能再指向別的地方了,它總是把它所指向的目標當作一個int常量。也可以寫成const int* const a;含義相同。
接下來三道算法設計題
第四道題:寫出int strlen(const char *str)方法,要求方法中不能有局部或者全局變量。
當時看到不能定義變量,想了好久也沒想到什么好辦法,回來搜了下原來是要用遞歸,下面是參考代碼:
int strlen(const char *str) { if(*str!='\0') { return 1 + strlen(++str); } else { return 0; } }
第五道題:題目大致意思是將一句英語句子調轉順序,但單詞內字符順序不變,例如:”The misson of Baidu is to provide the best way for people to find information.“
變為”information. find to people for way best the provide to is Baidu of misson The“,句子中的標點符號就當做單詞的一部分,不區分開來。
我用C實現的,代碼如下效率一般
#include<stdio.h> #include<string.h> int main() { int i,j,k,p,len,leni; char temp,s[1000]; leni=0; gets(s); len=strlen(s); for(i=0;i<(len/2);i++)//翻轉整個字符串 { temp=s[i]; s[i]=s[len-1-i]; s[len-1-i]=temp; } for(i=0;s[i]!='\0';) { for(j=i;(s[j]!=' ')&&(s[j]!='\0');j++) leni++; for(k=i,p=0;p<(leni/2);k++,p++)//翻轉每個單詞 { temp=s[k];//k從i處每一步加一 s[k]=s[i+leni-1-p];//單次尾部指針從i+leni-1處每次減一 s[i+leni-1-p]=temp; } leni=0; if(s[j]==' ')//跳過空格 i=j+1; else if(s[j]=='\0')//判斷是否結束 i=j; } puts(s); }
第六道題:從100萬個數里面找出10個最大的數。寫出代碼並分析復雜度。
這題直到最后還是沒想出好辦法,當然效率最低的辦法就是一次次遍歷,這樣要算1000萬次,明顯不是好辦法。
然后考慮分成多個線程計算,比如分成100組,每組1萬個數,從每組中找出最大的10個,再從得到的1000個中找出最大的10個,這樣大大提高了效率。
由於此題要寫出代碼,個人認為不是采用分組計算的方法,而是找出一種運算次數最少的方法,即時間復雜度最小。
試卷上我采用的是先構造一個10個數的數組並按照從小到大的順序排列,然后所有的100萬個數進行遍歷,如果比數組的第一個數還要小則跳到下一個數,若比它大,則替換掉第一個元素,然后對數組進行排序,直到所有的數遍歷完。這樣整個時間復雜度最壞為100萬*10log10。
網上的算法就是將上面的數組排序換成堆積排序,構建一個只有10個元素的堆,將根結點設為這10個數中最小的數,然后開始遍歷數組,如果遇到的數根結點還小,直接跳過,遇到比根結點大的數,就替代根結點,然后對這個進行排序,保證堆頭的特征。
希望各位大神指點,能給出更好的方案。
后面是系統設計題(這些題都比較開放,可以參考網上一些資料了解一下)
1:基於手機系統平台,設計一個IM多人實時語音聊天系統,包括手機端和Server端,請基於手機系統的一些特性,來設計這套IM系統。
2:請描述一下這套系統設計時需要考慮的關鍵性能指標有哪些。
3:如何保證實時語音的通話質量。
4:如何快速移植到多個手機系統平台(android和IOS)的方案。
5:請畫出手機端程序的系統結構圖。