九月份笔试题

九月份本人参加了华为、中兴、讯飞、英伟达的相关笔试,有一些笔试题感觉挺有意思,而且当时都没做出来,现在趁十一假期,把这些题都总结一下,以备不时之需。

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这篇博文~

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值