案例1
题目描述:求1+2+3+…+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。
我去,求和居然不让用乘除法,也不准我们用循环,如果单独这两个限制的话还好,我们还可以用地递归,例如:
f(int n){
if(n == 0){
return n;
}else{
return f(n-1) + n;
}
}
然后 if, else, case 等各种关键字也不给用,想着那我用三元运算符(A?B:C),然后这种具有判断语句的三元运算符也不给用,我去,这也太刁难了吧(当然,大佬直接秒杀的可以飘过)。
这道题肯定是必须用递归来解决的,而这递归的核心就是需要判断一下递归条件是否结束了,然而题目不准我们使用条件判断语句。那我们该怎么办呢?大家可以散发思维想一下哦。
其实我们可以下面这样的语句来代替 A?B:C 这样具有判断能力的三元运算符
n != 0 && (f(n-1) + n) != 0;0 && (f(n-1) + n) != 0;
这个 && 逻辑判断符的作用就是:如果 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 类型。
最后的代码如下
var sum;
function fn(n) {
sum = n;
(n != 0) && (sum += fn(n - 1)) != 0;
return sum;
}
console.log(fn(4));
案例 2
题目描述:写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。
我去,求和不准加减乘除!面试官,能不能别这么任性,好好的加减乘除居然不给用。
不过我相信大家第一时间都能想到用位运算来解决,可能在大学期间学过电路相关知识的一下就能把代码写出来了,不过有些人也能可能是一个位一个位来处理的。例如我先处理第一个位(这里指的是二进制位哈),看看有没进位,然后处理第二个位,如果第一个位有进位就加到第二个位来,然后处理第三个位…..
如果你是这种方法处理的,那么恭喜你,看完这道题你能有所收获。实际上上面那种解法也可以,只是太复杂了,可能各种判断。其实这道题可以这样解:这里为了方便讲解,我先给出代码,再给出具体的讲解,你看完代码再来看讲解可能更好理解
function Add(num1, num2) {
//不计进位的和
var a = (num2 ^ num1);
//进位的数
var b = (num2 & num1) << 1;
var c = a + b;
return c;
}
console.log(Add(123, 321));
大家想一个问题,如果我们把两个数进行异或,例如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。