1. A + B 问题

题目:给出两个整数 a 和 b , 求他们的和。

说明:a和b都是32位整数
题目一看很简单,只要 return a+b;即可。
但是直接return a+b 的效率并不高,效率只超过27%的人,边尝试其他方法,后面发现大家有使用位运算来进行操作。
但是一直对位运算不是很了解,于是便趁这个机会研究一下位运算。
我们知道计算机在进行加减运算时是使用补码进行运算的,那么在这里,我们来回顾一下二进制原码,补码,反码的知识。
注:因为题目a和b都是32位整数,所以一下均为在32位整数下的介绍,关于位操作的详细介绍参考:https://blog.csdn.net/briblue/article/details/70296326
那么,我们开始吧!

原码 反码 补码

原码:将一个数转换成二进制就是它的原码。(正数的符号位为,负数的符号位为1)

//以正数8和负数5为列
 8 = 0000 0000 0000 1000
-5 = 1000 0000 0000 0101

反码:正数的反码和原码一样,而负数的补码就是在原码的基础上,符号位不变,其他位置0变为1,1变为0。

//以正数8和负数5为列
 8  = 0000 0000 0000 1000
-5  = 1111 1111 1111 1010

补码:正数的补码还和原码一样,负数的补码是在原码的基础上加1。

//以正数8和负数5为列
 8 = 0000 0000 0000 1000
-5 = 1111 1111 1111 1011

那么我们上边提到过,计算机在进行运算时,本质就是二进制补码的运算

//那么8+(-5)的本质就是:
0000 0000 0000 1000 
1111 1111 1111 1011
相加得到的结果是
(1) 0000 0000 0000 0011
我们发现最前边多了一个1,因为进位问题这个1超过了16位,就被舍弃了,那么得到的结果就是
0000 0000 0000 0011 = 3
正好等于结果3(即8-5)

下边就要介绍一些常见的位运算符(&,|,^,>>,<<)

&与运算符

&运算符的计算规则是:只有当两个数都为1时,结果才为1,否则结果为0。

//以正数3和正数5为例(s即3&5)
3= 0000 0000 0000 0011
5= 0000 0000 0000 0101
s= 0000 0000 0000 0001 = 1
我们得到的结果为1(记住这个结果,后面我们会用到这个信息)
//以负数-3和正数5为例(s即-3&5)
-3 = 1111 1111 1111 1101
 5 = 0000 0000 0000 0101
 s = 0000 0000 0000 0101 = 5
我们得到的结果是5(不用过多的去纠结5和-3+5的结果2的关系,如果你迫不及待的话,可以跳过|或运算符直接去看^异或运算符)
|或运算符

|运算符的计算规则是:只要参与运算的有一个1,结果就为1,如果都为0,则结果为0。

//以正数3和正数5为例(s即3|5)
3= 0000 0000 0000 0011
5= 0000 0000 0000 0101
s= 0000 0000 0000 0111 = 7
我们得到的结果为7
//以负数-3和正数5为例(s即-3|5)
-3 = 1111 1111 1111 1101
 5 = 0000 0000 0000 0111
 s = 1111 1111 1111 1111 = 65535
我们的得到的结果是65535
^ 异或运算符

^运算符的计算规则是:只有当两个数不同时,才为1 。

//以正数3和正数5为例(s即3^5)
3= 0000 0000 0000 0011
5= 0000 0000 0000 0101
s= 0000 0000 0000 0110 = 6
我们得到的结果是6
这个时候我们先回想一下3+5的二进制运算过程
3= 0000 0000 0000 0011
5= 0000 0000 0000 0101
s= 0000 0000 0000 1000 = 8
如果上边为什么等于8不理解的话请看下边关于二进制加法的规则:
二进制运算时,从末位向前看,0+0=1,1+0=1,1+1= 10(即向前进一位,类似与10进制满十进1,二进制为满2进1)
好了,现在我们回到正题:怎么使用位运算来实现上述加法
(1)我们先来回顾一下3&5的过程
//以正数3和正数5为例(s即3&5)
3= 0000 0000 0000 0011
5= 0000 0000 0000 1001
s= 0000 0000 0000 0001 = 1
我们会发现,3&5的结果就是我们需要进位的那个值,只有为1+1时,我们才需要进位,而&运算保留的就是1+1位置的值
(2)我们在来看一下刚说过的^运算符
//以正数3和正数5为例(s即3^5)
3= 0000 0000 0000 0011
5= 0000 0000 0000 0101
s= 0000 0000 0000 0110 = 6
我们发现,^运算符保留的是一个位加法中一个为0,一个为1位数的值,这正是不需要进位的值,我们结合&和^运算符,是不是和二进制加法
的过程有点相似?
没错!&运算的结果是加法时需要进位的值,而^保留的是加法时不需要进位的值,而二进制的本质就是进位的值*2加上不进位值的结果,那么就是
&运算的结果*2+^运算的结果就是二进制运算的本质,我们来验证一下 ^运算的结果6+&运算的结果1*2结果正是我们要的8,即3+5;

看到这里,问题就迎刃而解,我们只要把a+b换成a^b+2*(a&b)即可,但是又出现新的问题,乘法的本质也是数个加法,我们这样反而把问题变得更加复杂,那么怎么解决乘法的问题呢,我们下边来介绍位移运算符。

<< 左移运算符

<<运算符的计算规则为:将数字整体向左移动一位,符号位不变,低位补0,<<后面跟数字几则为移动几位

//我们以3和5为例
3 = 0000 0000 0000 0011
3<<1 = 0000 0000 0000 0110 = 6
5 = 0000 0000 0000 0101
5<<1 = 0000 0000 0000 1010 = 10
我们发现3和5在位移一位后都变成原来的2倍,这是因为2进制是以2为单位(可以参考10进制,10进制左移一位,整体数值变大为原来的10倍)。
那么我们刚才乘2的问题就解决了,我们只需要将a^b+2*(a&b)更改为a^b+(a&b)<<即可。

现在问题从a+b变为了a^b+(a&b)<<,我们会发现a&b在位移后与前面的相加,仍是一个二进制加法,所以还是要使用刚才的方法,没错,这里就要使用递归,直到有一个数为0是,结束递归,那么我们直接来看代码吧。

public class Solution {
    /**
     * @param a: An integer
     * @param b: An integer
     * @return: The sum of a and b 
     */
    public int aplusb(int a, int b) {
        // write your code here
        if(a == 0)
            return b;
        if(b == 0)
            return a;
        int sum = (a&b)<<1;
         return aplusb(sum,a^b);
    }
}

以下为位运算的结果,我们可以看到效率的确是变高了。


位运算的结果

以下为直接return a+b的结果


不使用位运算
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容

  • 题目描述 给出两个整数a和b, 求他们的和, 但不能使用 + 等数学运算符 思路 二进制的数字用0、1表示,两数相...
    Yui丶西米大人阅读 529评论 0 0
  • 给出两个整数a和b, 求他们的和, 但不能使用 + 等数学运算符。不能用求和运算符肯定就是用一些最简单的逻辑运算符...
    和蔼的zhxing阅读 217评论 0 0
  • 我是小小强,这是我的第5篇原创文章,阅读需要大约10分钟。 题目 LintCode:A+B问题 描述 给出两个整数...
    我叫小小强阅读 277评论 0 3
  • 倒春寒格外漫长 感冒也得了一场严重 忍着困倦勉强 打着哈欠路过 门里撞开的 …… 你的酒窝
    Assumehui阅读 217评论 0 1
  • 今天是个好天气,一大早太阳照进屋子特别亮。 睡梦中,听到爸妈在讲话。 父亲脾气不太好但很会说话 母亲是个不太会说话...
    肥啊肥羊阅读 330评论 4 4