现在的位置: 首页 > 综合 > 正文

数据交换的特殊算法–经典面试题

2017年08月25日 ⁄ 综合 ⁄ 共 3405字 ⁄ 字号 评论关闭

今天我们接着来看几个面试题

 

1There are two int variables : a and b , don''t use "if","? :","switch" or

         other judgement statements , find out the biggest one of the two numbers.

        

        
这种题目,我是见过好几次了,这种题目和给你两个数ab,要求不使用任何中间变量

        
来将ab的值进行交换,这两种题目是很相似的,

        
都可归结为将ab之中最大值赋给a,将另一个赋给b。有点乱是吧,不要紧相信一会

        
你就会明白!

        

        
在讲解这个题目之前,我们不妨来看一个计算题,很简单的:

        
试计算下面算式的运算结果:(a+b)+|a-b|

        
看到这个题应该明白我为什么先讲这个算术题了吧!

        
这个算式隐含了一个规则如果a>=b那么结构就是2a,否则结果就是2b。到这已经很明显了

        
对于我们的这个面试题我们可以很容易的得出结果:a = (a+b) + |a-b|;

        

        
对于这个题还有另外一种做法,这种做法要求对数据类型的转换,

        
计算机中数据的存储方式,以及计算机的状态寄存器都要有一定的了解,

        
最起码应该知道相关的知识,不然我在这讲也没什么用!

                                                                 #include

                                                                                   

                                                                 int main(void)

                                                                 {

                                                                           int a , b ,c;

                                                                           unsigned d;

                                                                           char *strs[2] = {"a的值较大","b的值较大"};

                                                                           printf("请输入两个数:\n");

                                                                           while(scanf("%d%d",&a,&b) != 2);

                                                                           c = a - b;

                                                                           d = (unsigned)(c) ;

                                                                           d = d >>(sizeof(int)*8 - 1);       

                                                                           printf("%s",*(strs+d));

                                                                                   

                                                                           return 0;

                                                                 }

                  

                  
为了解释这中方法我特意写了这个程序:我们利用调试来跟踪一下;

                  
在这之前我们必须先讲一下有关数据在内存中的存储问题:

                  
所有的数据在计算机中都是以二进制形式存储的,正数最高位用0表示,

                 
负数最高位为1。这就是我们这个方法的关键。我们可以判断(a -b)的最高位

                  
0还是1。由于(a-b)结果是正还是负是未知的!(这是当然的了)。我们需要

                  
将这个结果转换为无符号数,然后通过移位知道将原来的最高位移到最低位

                  
就可以找到这个最高位了。         由于不能使用判断语句,

                  
我们也不能在这时与10比较。这个时候我们也使用了一个技巧,将结果输出来!

                  
直接输出移位后的结果,这样显然不太文雅,看看我们的程序是如何做的吧!

                  

                  
前面讲了通过移位来获取最高位,那么应该移几位呢?这个我们需要判断(a-b)

                  
有几位!sizeof(int)*8,首先判断有几个字节,然后计算位数!

 

                  
这个地方使用sizeof(unsigned)*8 结果也是一样的!我们可以通过在上面程序的最后加上下面的两句  

printf("The size of unsigned is %d\n",sizeof(unsigned));

printf("The size of int is %d\n",sizeof(int));

 

可以看到这两句的数据结果是一样的。

 

下面我们来讲另一个相关的题目:

试在不使用任何中间变量的情况下来讲a
b的值进行交换。

 

这个题存在一个不是太正确的方法:

有些人使用: a = a + b;

                              b = a –b;

                              a = a – b;

这样做一般也不会出什么问题,但是在计算机中即使几率很小的事件,也是会经常发生的。

所以我们写程序必须全面考虑,发现缺陷要及时修补。

这个程序在a b都不是太大的时候是没什么问题的,问题是在a b
可能是很大的数,他们之和会不会溢出,你考虑了吗?

 

既然这种方法有这么一个缺陷那还有没有什么好的方法呢?答案当然是肯定的!

下面我们来考虑一个问题 a = a^a;的结果是多少?b = 0^b;的结果又是多少?

如果你已经理解了上面这两个小问题,那么距这个题的解法也就不远了!

a = a^b;

b = a^b;//b= a(原来)^b(原来)^b(原来)

a = a^b;//a = a(原来)^b(原来)^(a(原来)^b(原来)^a(原来))

 

希望你可以看明白!注释中的ab都是指的一开始的ab

下面我们来举一个例子来简要的说明一下:

110010100111010  ---------------------25914

^  000001000001110--------------------------526

^  110010100111010

=  000000100001110

大家可以算一下其实理解a^b^c = a^c^b以及a^a= 0就可以了!

抱歉!评论已关闭.