九月份筆試題

九月份本人蔘加了華爲、中興、訊飛、英偉達的相關筆試,有一些筆試題感覺挺有意思,而且當時都沒做出來,現在趁十一假期,把這些題都總結一下,以備不時之需。

1、【中興】寫一段代碼判斷機器的高低字節序問題。

這個題目,在網上隨便搜一搜能搜出好多種解法:有用到位運算的,如下面的C程序:

int isBigEndian(void)
{
        unsigned short t=1;	
	assert(sizeof(unsigned short)==2);
	//t的二進制表示:如果機器是高字節序,則表示爲00000001 00000000b,則右移8位後,返回1
	//如果是低字節序,   則表示爲00000000 00000001b,則右移8位後,返回0     
	return t>>8;
}


 

因此以上代碼在intel平臺得到的返回值爲0,在motorola 68k 平臺得到的返回值爲1,測試的代碼如下:

#include<assert.h>
#include<stdio.h>
#include<stdlib.h>

int isBigEndian(void)
{
	
	unsigned short t=1;
	assert(sizeof(unsigned short)==2);
	return t>>8;
}

void main(){
	printf("當前運行平臺是%s序!",isBigEndian()?"高字節":"低字節");
	getchar();
}



除此之外還有巧妙運用聯合體的方法(相當的巧妙),實際上中興筆試題上有較大的篇幅在糾結這個字節序的問題,我們可以創建如下的一個聯合體:

 

union isBigEndian{
    unsigned short a_16;
    unsigned char  b_8[2];
};

在TCPL中有對聯合(union)的準確定義(當時本科學C語言時,直接帶過了,汗):聯合是可以(在不同時刻)保存不同類型和長度的對象的變量,編譯器負責跟蹤對象的長度和對齊要求!聯合提供了一種方式,以在單塊存儲區中管理不同類型的數據,而不需要在程序中嵌入任何同機器有關的信息。
因此,如果定義如上的一個聯合變量,給其中的a_16賦任意值(保證在其高低兩字節的字面量不同),然後按照其b_8數組變量打印即可判斷字節序,完整的代碼如下:

void main(){
	union isBigEndian var;
	var.a_16=0x1234;
	if(var.b_8[0]==0x12)  printf("當前運行平臺是高字節序!");
	else printf("當前運行平臺是低字節序!");
	getchar();
}

更多以及更詳細的可以看這裏

2、【訊飛】邏輯推理題:(取石子游戲)兩個人玩一種相互取乒乓球的遊戲,總共有100個乒乓球,取球的規則如下:1)兩個人循環往復的取,甲取完然後乙再取,...;2)每人每次至少要取1個球,至多取5個球;3)取到第100個,即最後一個球的算贏;問題是:如果讓你和一個人玩這個遊戲,並且你先取,你該如何取球才能保證你一定能取到最後的球:1)你第一次取多少個球?2)以後各次(除第一次外),你該如何取球?

實際上,這是我參加訊飛測試崗筆試的最後一道題,考察的是逆向思考的能力,因爲這個題目如果順序思考進行,其可能的勝負結構將構成一顆結點和層數都巨大的決策樹,但逆向考慮則不然:

當我們考察最後一輪取球(如果你先取,那麼你取完然後另一個人再取,這算一輪),要保證你取到第100個球,則必須保證你在該輪取完球之後,還剩下至少6個球,這樣對手在這一輪沒法取完所有的球(至多取5個)!單獨考慮只剩下6個球的情況,我需要做的就是,在上一輪我取球之後,總能保證在最後一輪對方取球的時候有6個球,這樣說可能很難理解,但假如我第一次取球X個,剩下100-X個球,該遊戲轉換成對手先取球,我再取球的輪次,最後一輪,對手取球之前,剛好剩下6個球,如何才能做到呢?

一種不難的方法是:保證我在第一次取球之後的各次取球數視對方的取球數而定,也即,如果對方取a個,那我剛好取6-a個,保證每輪取球爲6個,總的球數以每輪6個的速度遞減,因此要保證最後一輪取球前剛好有6個,則我第一次取球的多少至關重要!!!一種簡單的取法是我第一次取4個,剩下的96個球剛好是6的倍數,滿足保證最後一輪取球前剛好有6個的條件,因此,這個問題得到了這麼一條特殊的路徑,從而解決!

3、【英偉達】設計一個算法,改變一個32位無符號整數的部分位,函數聲明部分可參考如下:

void bits_modified(unit_32 &var,uint_8 high_bit, unit_8 low_bit, unit_32 value);

舉例:如一個無符號整數0x9F357D,如果用0x1234的值改變其中的第4~7位,則改變後的數爲:0x9F353D !

這個題目當時做的時候感覺也是沒什麼時間了,大致的思路是有的:各種位運算,左(右)移,與,和,或(異或)之類的。

具體的C++程序整理如下:

typedef unsigned int unit_32;
typedef unsigned char unit_8;
#define left_shift(n) ((unit_32)1<<n)
void bits_modified(unit_32 &var,unit_8 high_bit, unit_8 low_bit, unit_32 value);

void bits_modified(unit_32 &var,unit_8 high_bit, unit_8 low_bit, unit_32 value){
//var-要改變的值,value-參考值,high_bit & low_bit--位置遊標
	unit_32 mask=0; //定義一個位標記量,初始化爲0
	assert(high_bit<=31 && low_bit<=high_bit);
	for(unit_8 i=low_bit;i<=high_bit;i++)
     		mask^=left_shift(i); //將需要替換的位--置爲1
	var&=(~mask);//將var中需要替換的位先置0
//利用mask截取value中的[low_bit,high_bit]區間的位,其他位置0
	mask &= value;
//對var與mask進行異或(無進位加)操作,即可得到替換部分位之後的var
	var^=mask;
	return;
}

採用如下的測試樣例可以簡單的得到驗證:

void main(){
unit_32 var=0x009F357D;
unit_32 value=0x1234;
bits_modified(var,7,4,value);
printf("the var is 0x%x,after %d~%d bits have been substituted",var,4,7);
getchar();
}


 


 運行的結果正確:

 

4、【英偉達在線編程調整賽】多叉樹後序遍歷轉前序遍歷問題,具體的題目要求與解答可以參考wzb56這篇博文~

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章