1. 程式人生 > >2014完美世界校招筆試題及答案

2014完美世界校招筆試題及答案

明天要去完美筆試的緣故,特意在網上找了完美2014年的校招筆試題練手。可能是自己基礎比較薄弱的緣故吧,感覺筆試題還是很難的。答案都是我自己上網查資料做的,有不對的地方還希望小夥伴們能夠指正。選擇題第13題和最後一道程式設計題,實在是不會,還希望能有小夥伴給解答一下。

一、選擇題

4.在C++中,以下四類轉化,失敗時有可能引發std::bad_cast異常的是:B

A.static_cast   B.dynamic_cast      C.reinterpret_cast  D.const_cast

解析:C++中預定義了多個可用於建立異常物件的類。主要有以下幾種:

1)runtime_error類(定義於標頭檔案<stdexcept>中)是多個描述執行時錯誤的標準異常類的基類。類overflow_error描述了算術運算向上溢位的錯誤,即一個值太大,超出了C++能描述的範圍。類underflower_error描述了算術運算向上溢位的錯誤,即一個值太 小,超出了C++能描述的範圍。

2)logic_error類(定義於標頭檔案<stdexcept>中)是多個描述邏輯錯誤的標準異常類的基類。類invalid_argument描述的是將非法的實引數傳遞給函式的錯誤。類length_error 描述的是物件大小超過最大允許長度的錯誤。類out_of_range描述的是值超出允許範圍的錯誤。

3)類bad_alloc、bad_cast、bad_typeid和bad_exception描述了C++運算子丟擲的異常。bad_alloc異常是new運算子在無法分配記憶體時丟擲的。bad_cast異常是dynamic_cast運算子在沒有轉化為引用型別時丟擲的。bad_typeid異常是typeid運算子在運算物件為空指標時丟擲的。bad_exception類則是描述了從未預料的異常處理程式所丟擲的異常。

5.正則表示式中,用於匹配字串的開始位置的字元是:B

A.<            B.^            C.$            D.+

解析:^用於匹配字串的開始位置,$用於匹配字串的結束位置。

6.當對一個物件的改變需要同時改變其它物件,但它不知道其它物件是誰,並且也不知道具體有多少個物件有待改變時,我們應該使用:D

A.模板方法     B.責任鏈                  C.代理              D.觀察者

7.在X86體系中,以下哪個是棧頂指標暫存器:D

A.EAX       B.ECX       C.ESI                 D.ESP

解析:eax, ebx, ecx, edx, esi, edi, ebp, esp等都是X86 組合語言中CPU上的通用暫存器的名稱,是32位的暫存器。EAX 是"累加器"(accumulator), 它是很多加法乘法指令的預設暫存器。EBX 是"基地址"(base)暫存器, 在記憶體定址時存放基地址。ECX 是計數器(counter), 是重複(REP)字首指令和LOOP指令的內定計數器。EDX 則總是被用來放整數除法產生的餘數。ESI/EDI分別叫做"源/目標索引暫存器"(source/destination index),因為在很多字串操作指令中, DS:ESI指向源串,而ES:EDI指向目標串。EBP是"基址指標"(BASEPOINTER), 它最經常被用作高階語言函式呼叫的"框架指標"(frame pointer)。ESP 專門用作堆疊指標,被形象地稱為棧頂指標,堆疊的頂部是地址小的區域,壓入堆疊的資料越多,ESP也就越來越小。

8.假設有std::vector<int> v,數值依次為{12,17,17,22,22,23,30}。         Lower_bound(v.begin(),v.end(),17)和upper_bound(v.begin(),v.end(),22)所返回的iterator分別指向陣列中的第幾個值(假設從0開始):C

A.0,5        B.1,4        C.1,5        D.2,3

解析:lower_bound在排序的vector中進行二分查詢,查詢第一個大於等於的值,upper_bound在排序的vector中進行二分查詢,查詢第一個大於的值。

9.下列哪個C++關鍵字用於表示變數或者函式的定義在別的檔案中:B

A.static             B.extern           C.inline             D.default

解析:static是用來宣告靜態變數;extern可以置於變數或者函式前,以標示變數或者函式的定義在別的檔案中,提示編譯器遇到此變數和函式時在其他模組中尋找其定義;inline用於定義行內函數;default是用在switch語句結尾,表示其他情況。

10.print()函式是一個類的常成員函式,它無返回值,下列表示中正確的是:A

A.void print()const         B.const void print()         C.void const print()          D.void print(const)

解析:A中const是用來修飾成員函式,B的用法是用來修飾函式返回值,C無此類用法,D的用法是修飾函式傳遞的引數值。

11.對於int *pa[5]的描述,以下哪個選項是正確的:A

A.pa是一個具有5個元素的指標陣列,每個元素是一個int型別的指標

B.pa[5]表示某個陣列的第5個元素的值

C.pa是一個指向陣列的指標,所指向的陣列是5個int型別的元素

D.pa是一個指向某個陣列中第5個元素的指標,該元素是int型別的變數。

解析:int *pa[n]是指標陣列,[]優先順序高,先與pa結合成為一個數組,再由int*說明這是一個整型指標陣列,它有n個指標型別的陣列元素。int (*p)[n]是陣列指標,()優先順序高,首先說明p是一個指標,指向一個整型的一維陣列,這個一維陣列的長度是n,也可以說是p的步長。

12.inti=(int)((unsigned int)0xffffffff+(unsigned int)0xffffffff);

  printf(“%d”,i);結果是:C

A.0                    B.-1                   C.-2                   D.2

解析:計算機中是用補碼來存數字的。原碼中,最高位表示符號位,0為正,1為負。正數的反碼和補碼是其本身,負數的反碼是在原碼的基礎上,符號位不變,其餘位取反,補碼是反碼加1。因此0xffffffff在int型時表示時-1,在unsigned int中表示的是2^32-1。

13.由a,b,c組成的5位字串,aa至少出現過一次的共有多少個:

A.77                  B.78                  C.79                  D.80

這道題實在是不會了。。

14.已知有n個程序共享一個互斥段,如果最多允許m個程序(m<n)進入互斥段,則訊號量的變化範圍是:C

A.-m-1              B.-m-0              C.-(n-m)-m               D.-(m-1)-n

解析:當沒有程序進入互斥段時,訊號量為m;當有m個程序進入互斥段且有1個程序等待進入互斥段時,訊號量為-1;最多能有n-m程序等待進入互斥段,因此訊號量的變化範圍是-(n-m)~m。

15.師徒四人西天取經,途中必須跨過一座橋,四個人從橋的同一端出發,你得幫助他們到達另一端。天色很暗,而他們只有一隻手電筒。一次同時最多可以有兩人一起過橋,而過橋的時候必須持有手電筒,所以就得有人把手電筒帶來帶去,來回橋兩端。手電筒不能用丟的方式來傳遞。四個人的步行速度各不同,若兩人同行則以較慢者的速度為準。大師兄只需花1分鐘過橋,二師兄需花2分鐘過橋,三師兄需花5分鐘過橋,師父需花10分鐘過橋。請問他們最短在多少分鐘內能過橋:B

A.16                  B.17                  C.18                  D.19

解析:首先讓大師兄和二師兄過河,大師兄回來送手電筒,三師兄和師傅過河,二師兄回來送手電筒,大師兄和二師兄再一起過河。所需時間為2+1+10+2+2=17分鐘。

16.下面各項中屬於不可過載的一組運算子是:C

A.+、-、*、/          B.[ ]、( )           C.::、.、?:、sizeof、. *                 D.++、--

解析:大多數運算子都是可以過載的,不可過載的運算子很少,有作用域操作符 ::、條件操作符 ?:、點操作符 .、指向成員操作的指標操作符 ->*,.*、預處理符號 #和sizeof。

二、填空題

1.求下面函式的返回值

int func(int a)

{

int count=0;

while(a)

{

count++;

a=a&(a-1);

}

return count;

}

假設a=911,則函式返回值是:7

2.請簡單解釋以下三種頁面排程演算法的含義以及原理。

1)FIFO:先進先出排程演算法,根據頁面進入記憶體的時間先後選擇淘汰頁面,先進入記憶體的頁面先淘汰,後進入記憶體的後淘汰。

2)LRU:最近最不常用排程演算法,根據一段時間內頁面的訪問次數來選擇淘汰頁面,每次淘汰訪問次數最少的頁面

3)LFU:最近最少排程演算法,在選擇淘汰頁面時會考慮頁面最近的使用,總是選擇在最近一段時間以來最少使用的頁面予以淘汰。

3.給出至少兩種用於優化C++專案編譯時間的方法

1)刪除不必要的#include

2)刪除不必要的一大堆私有成員變數

3)刪除不必要的類之間的繼承

4.下面程式碼輸出什麼:>6

void foo(void)

{

unsigned int a=6;

int b=-20;

(a+b>6)?puts(“>6”):puts(“<=6”);

}

unsigned int和int型相加時,程式會自動按無符號數來計算,兩者相加的值為4294967282,遠遠大於6。

4.順序搜尋和二分搜尋代表了搜尋時間和預處理時間之間的折中,處理一個n元素      格時,需要執行多少次二分搜尋才能彌補對錶進行排序所消耗的預處理時  間?lgn

解析:順序搜尋的複雜度是O(n),二分搜尋的複雜度是O(lgn),但是二分查詢要求陣列有序。用複雜度低的排序演算法,比如快排,複雜度為O(nlgn)。假設需要x次,則x*n=nlgn+lgn*x,所以x=nlgn/(n-lgn),當n比較大時,x接近於lgn。

5.到商店裡買200的商品返還100優惠券(可以在本店代替現金),請問實際上折        扣是多少?6.7

解析:相當於花了200塊錢買了300塊錢的東西,所以折扣是200/300,6.7折。

6.若二叉樹中有n個度為2的結點,則該二叉樹中的葉子節點數為:n+1

解析:二叉樹的基本性質,度為0的結點個數為度為2的結點個數加上1。

7.寫出至少三種常見的設計模式,並簡單介紹其用法或目的:

1)觀察者模式:定義了一種一對多的依賴關係,讓多個觀察者物件同時監聽某一主題物件,在它的狀態發生變化時,會通知所有的觀察者

2)代理模式:為其他物件提供一種代理以控制對這個物件的訪問。在某些情況下,一個物件不適合或者不能直接引用另一個物件,而代理物件可以在客戶端和目標物件之間起到中介的作用。

3)模板方法模式:定義一個操作中的演算法的骨架,而將一些步驟延遲到子類中。模板方法使得子類可以不改變一個演算法的結構即可重定義該演算法的某些特定步驟。

9.寫出判斷float f是否等於零的if語句:if(x<0.000001f  && x>-0.000001f)

解析:由於精度的問題,float型不能用“==”直接來判斷,要判斷這個數是否在一個很小的區間內。

10.編譯時的多型性通過過載來實現。

解析:編譯時的多型性是通過函式過載和運算子過載實現的,執行時的多型性是通過繼承和虛擬函式來實現。

11.class A

{

public:

A(){}

virtual ~A(){}

char m_x;

};

A a;

sizeof(a)的值是:8

解析:虛擬函式放在虛表中,如果定義了虛擬函式,則需要存放一個指向虛表的指標。在C++中,指標佔4個位元組,char型別佔1個位元組,根據位元組對齊的原理,需要佔據8個位元組,因此類的大小為8。

12.C語言編譯器將源程式翻譯成二進位制可執行檔案,需要經過預處理、編譯和優化、彙編、連結等階段。

13.下面二叉樹的中序遍歷是:HDBEAFCG


三、簡答題

1.引用和指標的區別?

1)引用相當於是變數的一個別名;指標是指向變數的記憶體地址。

2)引用只能在定義時初始化一次,之後不可變;指標可變。

3)引用不能為空,指標可以為空。

2.怎麼理解TCP連線中的資料傳輸是無邊界的,在實際程式設計中需要怎樣處理。

TCP協議是無訊息邊界的,即不能保證來自單個send方法的資料能被單個receive方法讀取。比如:第一次傳送:abcdefg   第二次傳送:123456  接收方接收資料時,可能會出現以下情況:第一次接收:abcdefg123456   也可能出現:第一次接收:abc第二次接收:efg12第三次接收:3456

解決辦法:1)傳送固定長度的訊息。這種方適用於資訊長度固定的場合。2)將訊息長度與訊息一起傳送。這種方法增加了資料傳送資訊量,也增加了程式設計工作量。3)使用特殊標記分隔訊息。這種方法適合資訊本身不包含特殊標記的場合。如每傳送一行資訊,就可以用回車換行作為分隔符。

3.請你對快速排序、歸併排序和堆排序這3種演算法進行描述,並說明他們各自的適用條件。

快速排序:選擇陣列的第一個數作為主元,把所有比它小的數移到它的左邊,所有比它大的數移到它的右邊。以此遞迴該操作,直到整個陣列有序。

歸併排序:將陣列劃分為兩半,對每一半遞迴地進行歸併排序,當兩個子列表都已排序完畢,將它們合併為一個有序列表。

堆排序:堆排序的過程是先建立一個大根堆,大根堆的要求是每個節點的值都不大於其父節點的值。然後把根節點與最後一個葉子節點互換,再重新建立最大堆。遞迴執行,直到遍歷完整個陣列。

快速排序適用於原陣列是無序、隨機分佈的,歸併排序適用於要求排序穩定的場景,堆排序的最差情況下複雜度也為O(nlgn),適用於對最差情況下複雜度有要求的場景。

四、程式設計題

1.請自己用雙向連結串列實現一個佇列,佇列裡節點裡存的值為int,要求實現入隊,出隊和查詢指定結點的三個功能。

連結串列結點定義為:

struct node_t {

Int value;

node_t *prev;

node_t *next;

};

請實現如下三個函式並補齊需要成員:

class Queue{

……

void push_back(int value);

int pop_front();

node_t *find(int value);

};

解析:宣告一個head頭結點,執行push_back時,則在head前加入新插入的結點;執行pop_front()時,則返回head指向的值,並把頭結點刪除,讓head指向下一結點;執行find時,則依次遍歷連結串列,如果找不到值,就返回空。程式碼如下:

struct node_t
{
	int value;
	node_t *prev;
	node_t *next;
};
class Queue
{
public:
	Queue();
	void push_back(int value);
	int pop_front();
	node_t *find(int value);
private:
	node_t *head;
};
Queue::Queue()
{
	head=NULL;
}
void Queue::push_back(int value)
{
	if(head==NULL)
	{
		head=(node_t*)malloc(sizeof(node_t));
		head->value=value;
		head->next=NULL;
		head->prev=NULL;
	}
	else
	{
		node_t *newNode=(node_t*)malloc(sizeof(node_t));
		newNode->value=value;
		newNode->next=head;
		newNode->prev=NULL;
		head->prev=newNode;
		head=newNode;
	}
}
int Queue::pop_front()
{
	int value=head->value;
	node_t *temp=head->next;
	head->next=NULL;
	temp->prev=NULL;
	delete head;
	head=temp;
	return value;
}
node_t *Queue::find(int value)
{
	if(head==NULL)
		return head;
	node_t *temp=head;
	while(temp!=NULL)
	{
		if(temp->value==value)
		{
			return temp;
		}
		else
		{
			temp=temp->next;
		}
	}
	return NULL;
}

2.寫一個C/C++函式,判斷一個單鏈表是否具有環,如果存在環,則給出環的入口點。

解析:這是leetcode第142題,也是很常見的一道題。解析過程請見文章:http://blog.csdn.net/kevin_zhai/article/details/47656537。程式碼如下:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        if(head==NULL)
            return head;
        ListNode *fast=head,*slow=head;
        while(fast!=NULL&&fast->next!=NULL)
        {
            fast=fast->next->next;
            slow=slow->next;
            if(slow==fast)
            {
                break;
            }
        }
        if(fast==NULL||fast->next==NULL)
            return NULL;
        slow=head;
        while(slow!=fast)
        {
            fast=fast->next;
            slow=slow->next;
        }
        return fast;
    }
};

3.遊戲和圖形渲染中,物體間的碰撞檢測是很常見的需求。假設有一個可以抽象為凸邊形的物體和一個可以抽象為質點的物體,凸邊形各個頂點的座標和質點的座標都已知,設計一個演算法來檢測這兩個物體是否碰撞(即質點是否在凸邊形的內部或者邊上)。可以採用文字描述、虛擬碼或者真實程式碼來描述。

網上有很多解法,但都不太懂。推薦博文:http://blog.csdn.net/kaitiren/article/details/11913453