剑指offer47:1+2+3+...+n
题目:求1+2+3+...+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)
思路:位运算
代码:下拉到最后
注意点:
1. 短路特点: 作为"&&"和"||"操作符的操作数表达式,这些表达式在进行求值时,只要最终的结果已经可以确定是真或假,求值过程便告终止,这称之为短路求值(short-circuit evaluation)。这是这两个操作符的一个重要属性。
2. 位运算代替加减乘除:
2.1 加:a+b=(a^b)+(a&b)<<1
a^b:a+b没有进位的值;a&b:a+b的该进位的地方,(a&b)>>1,若进位不为0,则右移一位,表示进位后的值。
public int add(int a,int b) {
int res=a;
int xor=a^b;//得到原位和
int forward=(a&b)<<1;//得到进位和
if(forward!=0){//若进位和不为0,则递归求原位和+进位和
res=add(xor, forward);
}else{
res=xor;//若进位和为0,则此时原位和为所求和
}
return res;
}
2.2 减:a-b=a+(-b)=a+(~(b-1))
public int minus(int a,int b) {
int B=~(b-1);
return add(a, B);
}
2.3 乘:a*b= b中1的位置后面有i个0,a就右移i位,然后一起加起来得值。i=0,先res+=(a<<i),再b>>1,++i
public int multi(int a,int b){
int i=0;
int res=0;
while(b!=0){//乘数为0则结束
//处理乘数当前位
if((b&1)==1){
res+=(a<<i);
b=b>>1;
++i;//i记录当前位是第几位
}else{
b=b>>1;
++i;
}
}
return res;
}
2.4 除法:a/b= a中几个b,套用减法
public int sub(int a,int b) {
int res=-1;
return a < b ? 0 : sub(minus(a,b),b) + 1;
}
3. 代码:两个方法:
// 短路特性代替if,递归代替循环
public static int Sum_Solution1(int n) {
int sum = n;
boolean ans = (n > 0) && ((sum += Sum_Solution1(n - 1)) > 0);
return sum;
}
// 位运算代替乘除
// 等差数列求和 sn=(n*(n+1))/2
// (a=2^x1+2^x2+...+2^0)a的二进制
// a*b=b^x1+b^x2+...+b^0 b的根据a的二进制中1的位置左移
public static int Sum_Solution2(int n) {
return SumTest(n,n+1)>>1;
}
// 判断a的最后一位是否为1,若为1,则res+b;继续移位,a右移,b*2
public static int SumTest(int a,int b) {
int res=0;
boolean flag1=((a&1)!=0)&&(res+=b)>0;
a=a>>1;
b=b<<1;
boolean flag2=(a!=0)&&(res+=SumTest(a,b))>0;
return res;
}
位运算代替加减乘除: