一、簡答題
1.簡述數據庫以及線程死鎖產生的原理及必要條件,簡述如何避免死鎖。
2.請列舉面向對象設計的三個基本要素和五個主要涉及原則。
三個基本要素:封裝、繼承、多態。
五個基本原則:
(1)單一職責原則:就一個類而言,應該僅有一個引起它變化的原因。
(2)開放封閉原則:軟件實體對外擴展開放,對修改封閉。
(3)里氏替換原則:子類的實例能夠替換父類的實例。
(4)接口分離原則:採用多個專門的接口比使用單一的總接口要好。一個類對另一個類的
依賴性建立在最小的接口上。
(5)依賴倒置原則:依賴抽象不要依賴具體實現。、
3.簡述Windows內存管理的幾種方式及其優缺點。
(1)塊式管理。把主存分爲一大塊、一大塊的,當所需的程序片段不在主存時就分配一塊主存空間,把程序片段加載到主存,就算所需要的程序片段只有幾個字節也只能把這塊分配給它。優點:易於管理;缺點:浪費空間。
(2)頁式管理。把主存分爲一頁一頁的,每一頁的空間要比一塊一塊的空間小很多,顯然這種方式的空間利用率要比塊式管理高出很多。
(3)段式管理。把主存分爲一段一段的,每一段的空間又要比一頁一頁的空間小很多,這種方法在空間利用率上比頁式管理高出很多,但也有另外一個缺點,一個程序片段可能會被分爲幾十個段,這樣很多時間就會浪費在計算每一段的物理地址上。(I/O操作)
(4)段頁式管理。結合了段式管理和頁式管理的優點。把主存分爲若干頁,每一頁又分爲若干段。
二、算法和程序設計
1.公司組織一次羽毛球比賽,採用淘汰機制,假設公司有1001個人,如果要評出“公司羽毛球第一高手”的稱號,至少需要進行多少場比賽?請簡述設計過程,並寫出代碼模擬比賽過程。
/*
* 分析: 我們可以分輪來比賽,每一輪都有2個人去比賽,如果總數(person)是奇數,
*
* 則有一個輪空,否則全部參與比賽,淘汰一半(person/2),剩餘[person/2)+remain],
*
* 這裏,remain=person%2.,淘汰的人數亦即比賽的場數,加起來就構成了比賽場
*
* 數。
*/
public static void main(String[] args) {
int person = 1001; //當然person一般是由用戶來輸入的。
int result = 0, remain;
while (person > 0 && person != 1) {
result += person / 2; // 進行了比賽==淘汰的人數
remain = person % 2; // 有沒有人輪空
person /= 2; // 比賽後剩餘的人數
person += remain; // 要加上輪空的人
}
System.out.println("共進行:" + result + "場比賽");
}
2.一百個燈泡排成一排,第一輪將所有燈泡打開;第二輪每隔一個燈泡關掉一個。即排在偶
數的燈泡被關掉,第三輪每隔兩個燈泡,將開着的燈泡關掉,關掉的燈泡打開。依次類推,第100輪結束的時候,還有幾盞燈泡亮着。
//哈哈,這道題是在寧波實習的時候有個網友問我的,不幾天後就看到百度筆試有這道題,.
//真神奇啊!
//分析:
所有的檯燈,只有摁下的次數是奇數,那麼它一定是打開的,而對於檯燈X,如果其前面有基數個X的約數,例如:
4=1*2*4
9=1*3*9
16=1*2*4*8*16
而6=1*2*3*6 //偶數
因此,1~100內,查找X的約數個數爲奇數的數X即爲開着的檯燈。
public static void main(String[] args) {
//編碼就很簡單了.
for(int i=1;i<100;i++){
if(hasOddOddNumer(i)){
System.out.print(" "+i);
}
}
}
private static boolean hasOddOddNumer(int data) {
boolean result = false;
int approximateNumberCount = 0;
for (int i = 1; i <= data; i++) {
if (0 == data % i) {
approximateNumberCount++;
}
}
if (0 != approximateNumberCount % 2) {
result = true;
}
return result;
}
3.假定有20個有序數組,每個數組有500個數字,數字類型32位uint數值,現在需要取出
這10000個數字中最大的500個,怎麼做?
額,這個我看了別人給的方案,發現自己想錯了,僅貼出別人的算法:
從20個數組中各取一個數,並記錄每個數的來源數組,建立一個含20個元素的大根堆。 此時堆頂就是最大的數,取出堆頂元素,並從堆頂元素的來源數組中取下一個數加入堆,再取最大值,一直這樣進行500次即可。 時間複雜度:500*log2(20)
三、系統設計題
手機上通常採用九鍵鍵盤輸入。即:1-9個數字分別對應一定的英文字母(如:2對應ABC,
3對應DEF,...),因此,用戶可以方便的輸入中文內容。比如,用戶輸入“926”,可以對應
“WXYZ”,“ABC"和”MNO“的一系列組合”WAN”,“YAN"、”ZAO“等,這些對應“萬”,“嚴”,“早”
等漢字的中文拼音。
要求我們把這樣的輸入方式應用在我們的手機聯繫人查找功能上。有一個聯繫人列表
UserList,記錄了(姓名,手機號)這樣的組合,通過輸入的數字字符串NumStr,按照下面
的規則把對應的聯繫人查找出來,返回一個ReaultList。
規則:
1.手機號能連續部分匹配輸入的數字字符串NumStr。如輸入NumStr=926,則手機號爲
13926811111會被查出來;
2.聯繫人姓名中的漢字轉化成拼音後能夠連續匹配輸入數字字符串NumStr對應的英文字母
組合,如:輸入NumStr=926,則聯繫人“王二”、“萬事通”會被查找出來。因爲“王二”的“王”的
拼音“WANG”中含有“WAN”,和“926”能匹配。
輸入:
聯繫人列表UserList<UserName, PhoneNo>;漢字拼音射射表Dict,數字拼音字符串
NumStr。
輸出:
符合規則的聯繫人列表ResultList<UserName, PhoneNo>。
/*
對於這種題,我不知道考察的是什麼,其實我們應該可以自由假設自己的條件吧,然後根據自己的步驟來做出判斷,下面是我的一個思路,這個真不知道怎麼樣,還請高手們 不要笑話。
*/
設Phone phoneList<UserName, PhoneNo>存儲了所有聯繫人的信息;
首先,我們獲取“926”對應的所有拼音可能組成一個列表:
List<String> inputNameList=new ArrayList<String> ();
然後,把用戶輸入的字符串的所有可能add到inputNameList。例如,9,2,6就有3*3*3種可能都add到inputNameList裏面。
根據需求,用戶名和手機號關鍵字都可能存在滿足條件的情況,所以我們在一次遍歷phoneList的情況下分別判斷: (假設ResultList已經初始化,這裏不再做實例化)
for(Phone aPhone:phoneList ){
//電話號碼中是否含有字串 “926”
if(-1!=aPhone.getPhoneNo().indexOf(NumStr)){
ResultList.add(aPhone);
}
//我們根據姓獲取姓的拼音aDict,然後遍歷
//這個表,同樣用字串截取的辦法來判別。
String aDict=aPhone.getUserName().getDict();
for(String indexName :inputNameList){
If(-1!=aDict.indexOf(indexName )){
ResultList.add(aPhone);
}
}
}
這樣,這個ResultList就找到了。