PPS校園招聘筆試真題

思而思學(xué)網(wǎng)

如果大家想了解PPS每年校招筆試考查的知識點(diǎn),可以從PPS2015校園招聘筆試真題去總結(jié),相信大家一定會有所收獲。
一、簡答題

(1)一位老師有2個(gè)推理能力很強(qiáng)的學(xué)生,他告訴學(xué)生他手里有以下的牌:

黑桃:2 , 5 , 7 , 9 , J , K

紅心:3 , 4 , 9 , J , K

梅花:5 , 8 , 9 , Q

方塊:2 , 7 , 8

然后從中拿出一張牌,告訴A這張牌的大小,告訴了B這張牌的花色;

A:我不知道這張是什么牌

B:我就知道你肯定不知道這張是什么牌

A:現(xiàn)在我知道

B:現(xiàn)在我也知道了

請問這張是什么牌?

答:方塊8

(2)有11個(gè)乒乓球,其中有一個(gè)球是偽劣產(chǎn)品并存在質(zhì)量較輕的問題,現(xiàn)有一個(gè)沒有砝碼的天平,只能稱3次把那個(gè)假貨給稱出來。

答:

第一次,天平兩端各放5個(gè)乒乓球,如果天平平衡,那么剩下的那個(gè)就是偽劣產(chǎn)品。

如果不平衡,則將天平較輕那端的5個(gè)乒乓球選出來,然后在天平兩端各放2個(gè)乒乓球,如果天平平衡,那么剩下的那個(gè)就是偽劣產(chǎn)品。否則,將天平較輕那端的2個(gè)乒乓球選出來,放在天平上重新測量,天平較輕端的那個(gè)乒乓球就是偽劣產(chǎn)品。

(3)說明指針與引用的區(qū)別。

答:●指針是一個(gè)實(shí)體,而引用僅是個(gè)別名;

●引用只能在定義時(shí)被初始化一次,之后不可變;指針可變;引用“從一而終”,指針可以“見異思遷”;

●引用沒有const,指針有const,const的指針不可變;

●引用不能為空,指針可以為空;

●“sizeof 引用”得到的是所指向的變量(對象)的大小,而“sizeof 指針”得到的是指針本身的大小;

●指針和引用的自增(++)運(yùn)算意義不一樣;

●引用是類型安全的,而指針不是 (引用比指針多了類型檢查

從內(nèi)存分配上看:程序?yàn)橹羔樧兞糠峙鋬?nèi)存區(qū)域,而引用不分配內(nèi)存區(qū)域。指針:指向另一個(gè)內(nèi)存空間的變量,我們可以通過它來索引另一個(gè)內(nèi)存空間的內(nèi)容,本身有自己的內(nèi)存空間。

(4)列出C++類型轉(zhuǎn)換操作符,并分別舉例。

dynamic_cast: 在多態(tài)類型轉(zhuǎn)換時(shí)使用,用來執(zhí)行繼承體系中"安全的向下轉(zhuǎn)型或跨系轉(zhuǎn)型動作",就是子類對象指針轉(zhuǎn)化為父類對象指針。實(shí)現(xiàn)在運(yùn)行時(shí),并進(jìn)行運(yùn)行時(shí)檢測,如果轉(zhuǎn)換失敗,返回值是NULL。

static_cast:與dynamic_cast相反,static_cast是在編譯時(shí)轉(zhuǎn)換類型的,故稱為static_cast,它可以用在值類型轉(zhuǎn)換中

const_cast:一般用于去除const, volatile等修飾屬性上.

reinterPt_cast:特意用于底層的強(qiáng)制轉(zhuǎn)型,這個(gè)操作符能夠在非相關(guān)的類型之間轉(zhuǎn)換。操作結(jié)果只是簡單的從一個(gè)指針到別的指針的值的二進(jìn)制拷貝。在類型之間指向的內(nèi)容不做任何類型的檢查和轉(zhuǎn)換。

(5)寫個(gè)簡單的函數(shù),用于判斷CPU的字節(jié)序(little endian/big endian)

[cpp] view plaincopy//若處理器是Big_endian的,則返回0;若是Little_endian的,則返回1。

int checkCPU(void)

{

union

{

int a;

char b;

}c;

c.a = 1;

return (c.b == 1);

}

(6)實(shí)現(xiàn)一個(gè)128位整數(shù)的類,并且完成后面的函數(shù),測試一個(gè)數(shù)是否為素?cái)?shù)。

class int128

{

};

bool isPrime(int128 & number)

{

...

}

答:

[cpp] view plaincopy#include

#include

#include

#include

#include

using namespace std;

class int128;

void shift(int128 & in,deque & de);

template

bool operator<(bitset const& b1,bitset const& b2)

{

int i=N;

while( i-- && b1[i]==b2[i] ) { }

return ((-1 == i) ? false : (b1[i]

}

class int128

{

bitset<128> number;

public:

explicit int128(string str):number(str){}

int128(bitset<128>const& b):number(b){}

int128(int a = 0 , int b = 0 , int c = 0 , int d = 0)

{

bitset<32> b1(a),b2(b),b3(c),b4(d);

int i, k = 128;

for(i = 32 ; i ; number[--k] = b1[--i]) { }

for(i = 32 ; i ; number[--k] = b2[--i]) { }

for(i = 32 ; i ; number[--k] = b3[--i]) { }

for(i = 32 ; i ; number[--k] = b4[--i]) { }

}

bool operator[](size_t i)const

{

return number[i];

}

bitset<128>::reference operator[](size_t i)

{

return number[i];

}

friend bool operator<(int128 const& i1,int128 const& i2)

{

return i1.number < i2.number;

}

friend int128 operator+(int128 const& i1,int128 const& i2)

{

if(i1 == 0)

return i2;

if(i2 == 0)

return i1;

int128 result;

bitset<2> sum;

for(int i = 0 ; i < 128 ; ++i)

{

sum=i1[i]+i2[i]+sum.to_ulong();

result[i]=sum[0];

sum>>=1;

}

return result;

}

friend int128 operator-(int128 const& i1,int128 const& i2)

{

if(i2==0)

return i1;

int128 result=i1;

for(int i = 0 ; i < 128 ; ++i)

{

if(i2[i] == 0) {}

else

{

if(result[i] == 1)

result[i] = 0;

else

{

int k = i;

while(k < 128 && result[k] == 0)

{

result[k] = 1;

++k;

}

if(k != 128)

result[k] = 0;

}

}

}

return result;

}

friend int128 operator(int128 const& i1,int128 const& i2)

{

if(i1==0 || i2==0)

return int128();

if(i1==1)

return i2;

if(i2==1)

return i1;

int128 acc=int128();

for(int i=0;i<128;++i)

{

if(i2[i]==1)

{

acc=acc+(i1<

}

}

return acc;

}

friend int128 operator/(int128 const& i1,int128 const& i2)

{

if(i1 < i2)

return int128();

deque de;

bool flag = 0;

for(int i = 127 ; i >= 0 ; --i)

{

if(flag == 0 && i1[i] == 0) {}

else

{

flag = 1;

de.push_back(i1[i]);

}

}

int128 span = int128();

int128 result = int128();

while(!de.empty())

{

shift(span,de);

if(span < i2)

{

result = result<<1;

}

else

{

result = (result<<1) + int128(0,0,0,1);

span = span - i2;

}

}

return result;

}

friend int128 operator%(int128 const& i1,int128 const& i2)

{

if(i1 < i2)

return i1;

deque de;

bool flag = 0;

for(int i = 127 ; i >= 0 ; --i)

{

if(flag == 0 && i1[i] == 0) {}

else

{

flag = 1;

de.push_back(i1[i]);

}

}

int128 span = int128();

int128 result = int128();

while(!de.empty())

{

shift(span,de);

if(span < i2)

{

result = result<<1;

}

else

{

result = (result<<1) + int128(0,0,0,1);

span = span - i2;

}

}

return span;

}

friend bool operator==(int128 const& i,int const k)

{

bitset<32> bb(k);

for(int g = 0 ; g < 32 ; ++g)

{

if(i[g] != bb[g])

return 0;

}

return 1;

}

void operator=(bitset<128>const& b)

{

number = b;

}

friend ostream& operator<<(ostream& o,int128 const& i)

{

o<

return o;

}

int128 operator<<(size_t step)const

{

return int128(number<

}

unsigned long to_ulong()const

{

return ((unsigned long)&number);

}

public:

bool ToDecimalStr(std::string &str)

{

str.clear();

char buf[128] = {0};

int128 Radix(0, 0, 0, 10);

for(int128 num = number; !(num == 0); num = num/Radix)

{

if( sprintf_s(buf, 64, "%d", ((int)(num%Radix).to_ulong())) < 0 )

{

return false;

}

str = buf + str;

}

return true;

}

static void Print(int128 & data, bool bEndl = true)

{

string str;

if( data.ToDecimalStr(str) )

{

printf("%s%s", str.c_str(), (bEndl?"\n":""));

}

}

};

static int128 const one = int128(0,0,0,1);

template

void add_one(bitset& b)

{

int i = 0;

while(i < N && b[i] == 1)

{

b[i] = 0;

++i;

}

if(i == N)

return;

b[i] = 1;

}

void add_one(int128& k)

{

int i = 0;

while(i < 128 && k[i] == 1)

{

k[i] = 0;

++i;

}

if(i == 128)

return;

k[i] = 1;

}

void shift(int128 & in,deque & de)

{

if(de.front()==1)

{

de.pop_front();

in=(in<<1)+one;

}

else

{

de.pop_front();

in=in<<1;

}

}

bool IsPrime(int128 const& number)

{

for(int128 i = int128(0,0,0,2) ; i < number ; add_one(i))

{

if(number%i == 0)

return 0;

}

return 1;

}

(7)對二叉樹進(jìn)行排序,排序后的結(jié)果為二叉排序樹。

二叉排序樹又稱二叉查找樹,它或者是一棵空樹,或者是具有下列性質(zhì)的二叉樹:(1)若左子樹不空,則左子樹上所有結(jié)點(diǎn)的值均小于它的根結(jié)點(diǎn)的值;(2)若右子樹不空,則右子樹上所有結(jié)點(diǎn)的值均大于它的根結(jié)點(diǎn)的值;(3)左、右子樹也分別為二叉排序樹;

struct STreeNode

{

int key;

STreeNode left_child;

STreeNode right_child;

};

//返回值為排序后的根節(jié)點(diǎn)

STreeNode bt2bst(STreeNode root_node)

{

}

[cpp] view plaincopystruct STreeNode

{

int key;

STreeNode left_child;

STreeNode right_child;

};

void InsertBST(STreeNode t , int key)

{

if(NULL == t)

{

t = new STreeNode;

t->left_child = t->right_child = NULL;

t->key = key;

return;

}

if(key < t->key)

InsertBST(t->left_child , key);

else

InsertBST(t->right_child , key );

}

//先序遍歷樹并插入建立排序樹

void PreOrder(STreeNode t , STreeNode tBST)

{

if(NULL != t)

{

InsertBST(tBST , t->key);

PreOrder(t->left_child , tBST);

PreOrder(t->right_child , tBST);

}

}

//目標(biāo)函數(shù)

STreeNode bt2bst(STreeNode root_node)

{

STreeNode bstTreeRoot = NULL;

PreOrder(root_node , bstTreeRoot);

return bstTreeRoot;

}

二、擴(kuò)展題

(1)列出幾種你了解的IPC機(jī)制。

答:共享內(nèi)存:是一片指定的物理內(nèi)存區(qū)域,這個(gè)區(qū)域通常是在存放正常程序數(shù)據(jù)區(qū)域的外面, 它允許兩個(gè)或多個(gè)進(jìn)程共享一給定的存儲區(qū),是針對其他通信機(jī)制運(yùn)行效率較低而設(shè)計(jì)的。使得多個(gè)進(jìn)程可以訪問同一塊內(nèi)存空間,是最快的可用IPC形式。往往與其它通信機(jī)制,如信號量結(jié)合使用,來達(dá)到進(jìn)程間的同步及互斥。

信號量(semaphore):主要作為進(jìn)程間以及同一進(jìn)程不同線程之間的同步手段。

套接口(Socket):更為一般的進(jìn)程間通信機(jī)制,可用于不同機(jī)器之間的進(jìn)程間通信。起初是由Unix系統(tǒng)的BSD分支開發(fā)出來的,但現(xiàn)在一般可以移植到其它類Unix系統(tǒng)上。

消息隊(duì)列(MessageQueue)是一個(gè)結(jié)構(gòu)化的排序內(nèi)存段表,這個(gè)隊(duì)列是進(jìn)程存放或檢索數(shù)據(jù)的地方,是一個(gè)消息的鏈表,可以被多個(gè)進(jìn)程所共享。

(2)列舉一種死鎖發(fā)生的場景,并給出解決方案。

答:最經(jīng)典的場景就是生產(chǎn)者/消費(fèi)者,生產(chǎn)者線程生產(chǎn)物品,然后將物品放置在一個(gè)空緩沖區(qū)中供消費(fèi)者線程消費(fèi)。消費(fèi)者線程從緩沖區(qū)中獲得物品,然后釋放緩沖區(qū)。由于生產(chǎn)者/消費(fèi)者都在操作緩沖區(qū),容易導(dǎo)致死鎖的發(fā)生。

可以通過添加鎖的保護(hù)來對緩沖區(qū)進(jìn)行互斥的訪問,保證某一時(shí)刻只有一個(gè)線程對緩沖區(qū)進(jìn)行操作,當(dāng)緩沖區(qū)滿的時(shí)候,生產(chǎn)者線程就會掛起,同時(shí)通知消費(fèi)者線程。而緩沖區(qū)空的時(shí)候,消費(fèi)者線程就會掛起,同時(shí)通知生產(chǎn)者線程。

(3)列舉編寫一個(gè)TCP的服務(wù)器端程序可能需要用到的socket API,如果這些API的調(diào)用有先后關(guān)系,請按先后關(guān)系列出。

(4)舉例說明什么是MVC。

答:MVC是一個(gè)設(shè)計(jì)模式,它強(qiáng)制性的使應(yīng)用程序的輸入、處理和輸出分開。使用MVC應(yīng)用程序被分成三個(gè)核心部件:模型、視圖、控制器。它們各自處理自己的任務(wù)。

視圖是用戶看到并與之交互的界面。對老式的Web應(yīng)用程序來說,視圖就是由HTML元素組成的界面,在新式的Web應(yīng)用程序中,HTML依舊在視圖中扮演著重要的角色,作為視圖來講,它只是作為一種輸出數(shù)據(jù)并允許用戶操縱的方式。

模型表示企業(yè)數(shù)據(jù)和業(yè)務(wù)規(guī)則。在MVC的三個(gè)部件中,模型擁有最多的處理任務(wù)。由于應(yīng)用于模型的代碼只需寫一次就可以被多個(gè)視圖重用,所以減少了代碼的重復(fù)性。

控制器接受用戶的輸入并調(diào)用模型和視圖去完成用戶的需求。所以當(dāng)單擊Web頁面中的超鏈接和發(fā)送HTML表單時(shí),控制器本身不輸出任何東西和做任何處理。它只是接收請求并決定調(diào)用哪個(gè)模型構(gòu)件去處理請求,然后用確定用哪個(gè)視圖來顯示模型處理返回的數(shù)據(jù)。 更多熱門筆試題目分享:
軟通動力C語言筆試題目
阿爾卡特朗訊射頻類筆試題
惠普java和數(shù)據(jù)庫招聘筆試題

熱門推薦

最新文章