[leetCode]面试题64. 求1+2+······+n
如果抛开本题的前提条件,直接用递归可以按以下方式求解:
class Solution {
public:
int sumNums(int n) {
return n==0?0:n+sumNums(n-1);
}
};
但是题目有限制,因此剩余的工具只有加减法,赋值,位运算符以及逻辑运算符。
解法一 递归
利用逻辑运算符的"短路"性质来作为递归的出口。以 &&
为例,在表达式A && B
中,当A为false时整个表达式为false,B不会执行,因此A可以看作递归出口,B可以看作递归函数主体:
使用&&
class Solution {
public:
int sumNums(int n) {
n && (n += sumNums(n-1));
return n;
}
};
class Solution {
public int sumNums(int n) {
boolean flag = n > 0 && (n+=(sumNums(n-1))) > 0;
return n;
}
}
使用||
class Solution {
public:
int sumNums(int n) {
!n || (n += sumNums(n-1));
return n;
}
};
解法二 快速乘
由于不能使用乘除法,但是我们可以使用移位运算符与加减法来模拟"二进制乘法"。二进制乘法求解过程如下图所示:
我们111作为A,1011作为B,A与B相乘可以看作"加法"与"移位"。如果B的第i位(i=0,1,2,3)为1则A对结果的贡献为A<<i,因此可以通过以下代码来实现该乘法:
int quickMuliti(int A, int B){
int ans = 0;
for(;B;B>>=1){
if(B & 1){//判断B二进制的最低位是否是1
ans+=A;
}
A<<=1;
}
return ans;
}
回到本题,我们知道1+2+...n=(n+1)n/2
除法可以使用右移一位代替,那么等式就变成了(n+1)n>>2
,最后(n+1)n
可以用上面的快速乘来代替乘法,但是上面的代码有for
语句,而题目中n的范围为[1-10000]
所以n不会超过14位(10000转化为二进制为10011100010000),因此可以利用逻辑运算符的短路性质和移位运算符手动模拟乘法:
c++
class Solution {
public:
int sumNums(int n) {
int ans = 0, A = n, B = n+1;
(B & 1) && (ans+=A);
A<<=1;
B>>=1;
(B & 1) && (ans+=A);
A<<=1;
B>>=1;
(B & 1) && (ans+=A);
A<<=1;
B>>=1;
(B & 1) && (ans+=A);
A<<=1;
B>>=1;
(B & 1) && (ans+=A);
A<<=1;
B>>=1;
(B & 1) && (ans+=A);
A<<=1;
B>>=1;
(B & 1) && (ans+=A);
A<<=1;
B>>=1;
(B & 1) && (ans+=A);
A<<=1;
B>>=1;
(B & 1) && (ans+=A);
A<<=1;
B>>=1;
(B & 1) && (ans+=A);
A<<=1;
B>>=1;
(B & 1) && (ans+=A);
A<<=1;
B>>=1;
(B & 1) && (ans+=A);
A<<=1;
B>>=1;
(B & 1) && (ans+=A);
A<<=1;
B>>=1;
(B & 1) && (ans+=A);
A<<=1;
B>>=1;
return ans>>1;
}
};
java
class Solution {
public int sumNums(int n) {
int ans = 0, A = n, B = n + 1;
boolean flag;
flag = (B & 1)>0 && (ans+=A)>0;
A<<=1;
B>>=1;
flag = (B & 1)>0 && (ans+=A)>0;
A<<=1;
B>>=1;
flag = (B & 1)>0 && (ans+=A)>0;
A<<=1;
B>>=1;
flag = (B & 1)>0 && (ans+=A)>0;
A<<=1;
B>>=1;
flag = (B & 1)>0 && (ans+=A)>0;
A<<=1;
B>>=1;
flag = (B & 1)>0 && (ans+=A)>0;
A<<=1;
B>>=1;
flag = (B & 1)>0 && (ans+=A)>0;
A<<=1;
B>>=1;
flag = (B & 1)>0 && (ans+=A)>0;
A<<=1;
B>>=1;
flag = (B & 1)>0 && (ans+=A)>0;
A<<=1;
B>>=1;
flag = (B & 1)>0 && (ans+=A)>0;
A<<=1;
B>>=1;
flag = (B & 1)>0 && (ans+=A)>0;
A<<=1;
B>>=1;
flag = (B & 1)>0 && (ans+=A)>0;
A<<=1;
B>>=1;
flag = (B & 1)>0 && (ans+=A)>0;
A<<=1;
B>>=1;
flag = (B & 1)>0 && (ans+=A)>0;
A<<=1;
B>>=1;
return ans>>1;
}
}