三道“变态”的笔试题解析
01_计算1到n的累加
题目描述:
求1+2+3+…+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。
解题思路:
竟然不能用乘除法和循环以及条件判断语句,乍一看这也太变态了吧。还好可以用加法!用递归来代替循环,然后从n+n-1开始,一直加到n=0结束。那么问题是,如何判断n!=0呢? 这里便用到一个基本的运算符 "&&" ,与运算符在运行时,只有两边都为真,结果才为真,那么只要前面条件为假,后面的运算将不再进行。伪代码表示:
if n!=0
sum+=f(n-1)
Java代码实现如下:
public static int f(int n) { int sum = n; boolean t = (n != 0) && (sum = sum + f(n - 1)) != 0; return sum; }
这个 && 逻辑判断符的作用就是:如果 n != 0 成立的话,那么逻辑判断符后面的判断语句 (f(n-1) + n ) != 0 也会执行, 如果 n!= 0 不成立的话,那么后面的判断语句 ((f(n-1) + n)) != 0 就不会执行,通过这种方法,就可以达到我们递归结束条件判断的目的了。
这里说明一下,(f(n-1) + n) != 0 这条判断语句是没有任意其他含义的,我们的目的是为了执行 f(n-1)+n,之所以加上个 != 0 的判断,是因为逻辑 判断符号 && 只支持 boolean 类型,不支持 int 类型。
02_两个数相乘
题目描述:
实现两个整数的相乘,不能使用乘法运算符和循环
解题思路:
这个题可能就比较简单了,不能使用乘法和循环,但我们可以使用除法呀,
A*B=A/(1/B)
Java代码实现如下:
public static int mult(int a, int b) { return b != 0 ? (int) (a / (1.0 / b) + 0.99) : 0; }
- 一行代码搞定,如果b!=0 那么就让a乘1/b,反之结果为0。
但是这里有个问题,1/b数据类型为double,而两个整数相乘结果必然为整数,这里需要int进行转化类型,但是除法可能会导致后面尾数的丢失,所以我补了个0.99。注意,进行 int 类型转化时,小于 1 就行当做0处理。0.99又会被舍去。不影响最终结果。
03_求两数之和
题目描述:
写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。
解题思路:
方法一:
- 在绞尽脑汁之后,想到了数电曾学过的异或运算。如果我们把两个数进行异或,例如num1 = 101, num2 = 001,做异或运算:tmp = num1 ^ num2,结果是 tmp =100。那么此时得到的结果 tmp 其实就是两个数(num1,num2)各个二进制位上相加,不算进位的结果。而 num1 = (num1 & num2)<<1的结果就是两个数相加时那些需要进位的二进制位。例如 (101 & 001)<< 1=010,那么两个数第一位相加需要进位,我们需要把进的 那一位最后加到第二位上去。 说白就是 a + b = a ^ b + (a & b) << 1。 代码中,如果 num1 == 0的话,代表没有进位了,此时就可以退出循环了。
Java代码实现如下:
public static int Add(int num1, int num2) { int tmp = 0; while (num1 != 0) { tmp = num1 ^ num2; num1 = (num1 & num2) << 1; num2 = tmp; } return num2;
方法二:
- java方法库中有一个BigInteger的方法,它可以表示任意大的数,而这个方法的四则运算也都是用函数来进行,不会涉及四则运算符号,也算是投机取巧了一次。
Java代码实现如下:
public static int Add(int num1, int num2) { BigInteger b1 = new BigInteger(String.valueOf(num1)); BigInteger b2 = new BigInteger(String.valueOf(num2)); return b1.add(b2).intValue(); }