赞
踩
说好的每日一题的我懒惰了,今日的我又来了,我看到这个题的一瞬间,我觉得我今天超级顺畅,结果,我自闭了,因为想不出来,去操场跑了十圈(早上有运动过了,一般一天只运动一次),最后还是没想出来。但是就在我快要放弃时,我洗澡时灵感一现,我想出来了。想通了,我就来了。(不管怎样的打卡界面,我所展示的都是自己最真实的一面,努力与没努力我自己也看得见,大家一起来打卡呀!)
给你两个整数 a 和 b ,不使用 运算符 + 和 - ,计算并返回两整数之和。
看到题目的第一瞬间,我不屑一顾,再一看题目,我人傻了。说好的快乐呢?不能用+ - 运算符,整个人没了,我就一个劲的在哪里尝试,我就知道它肯定时利用二进制计算的我就在哪里尝试,进位,与运算,异或运算,我知道加法一定是这样子来到,在我不断地尝试中,嗯,我做出来了,但我不知道怎么解释。于是另辟新经,拉来了另一位大佬,与我一起讨论,结果我们不停得出结论,推翻结论,最后什么结论都没有得出。。。于是想要问问我们的终极大佬——老师,结果下课的时候,老师还在给别人讲代码,我。。等呀等,嗯,没等到,我就自己跑步去,流流汗啥的,在我洗澡时,这里复习一下&运算和^运算,(0&0=0,(0&1=1&0=0),1&1=1),(0^0=0,0^1=1^0=1,1^1=0),然后我们举两个例子先看看,先举一个a=2和b=3,他们二进制形式为a=0010,b=0011,a^b=0001,a&b=0010,a+b=0101,有一点点感觉,异或下来的值和最后两位与和一样,是错觉吗,再试一个数,a=13=00001101,b=14=00001110,a^b=00000011,a&b=00001100,a+b=27=00011011,感觉又不对了,怎么总感觉差点什么,于是不放心的我在试了一组,差距比较大的数,a=17=00010001,b=7=00000111,a^b=00010111,a&b=00000001,a+b=24=00011000,嗯,就是看起来这么毫无规律,就在我要放弃时,我又想到了进位,进位什么时候会用呢,嗯一般做与运算时会用到,于是我又抱着试一试的心态继续前进,发现做与运算是干嘛呢,与运算就是可以将二进制里面最右边的那个1找到,那么按照原理来讲,我们只要循环下去,我们就能找到我们最右边的那个1了,也就是我们需要进位的那个1,然后这时我又发现了前面的异或和+之间的“秘密”,在我们没发生进位之前的数,即2进制对应的两个数都不是1的时候,我们的异或值一定会和我们和的值相同,因为0+0=0,而异或时0^0=0,0+1=1+0=1,0^1=1^0=1,1+1=进位10,即当前位还是0,0^0=0,所以我们只要一直用(a\b)>>1进位的方式,一直取寻找最右边的那个数,那么我们迟早会将我们的进位的哪一个数字找出,并且此时如果在进位的话,a^0=a,a&0=0,这样子,最右边的数没变,但是我们就就通过&运算加上进位的方式做出来了2进制的进位效果,那么具体的代码怎么实现呢?
public int getSum(int a, int b) {
while (b!=0){
//这里通过用&来找到最右边的那个1,因为两个均为1时需要进位
//所以这里当同时为1时,我们就虚拟进位
//因为a&b>>1时不会对全1后面的数据有改变的,所以每一次得到的就是最右边的那个1
int n = (a&b)<<1;
//那么为什么这里会有异或呢?,这样是为了保证我们进位的哪一个数字由0变1
//而由于进位过后,原本有位1的数字也需要变成0
a=a^b;
b=n;
}
return a;
}
leetCode运行截图
番外:
抱着不服气的方式,我试了试直接return a+b,我i仿佛才明白为啥会有这道题,看下面运行截图:
(我以为我在天花板,结果我还在地狱,/苦涩)
抱着搞事情的心态,我又去试了试“-”法,嗯,我做出来了,不然我也不会说呀,我们减去一个数,不就是去加上他的相反数吗?嗯,那二进制还真就有相反数这个概念“~”,就是这个符号,于是,上代码!
public static int jian(int a , int b ){
int jian=0;
if(a==b){
return 0;
}
else {
//调用sum函数,就可了
jian = sum(a, ~b + 1);
}
return jian;
}
ps:每日一句毒鸡汤:钱对你真的就那么重要吗?写了好几个小时了,一个也不给打赏。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。