Calculate the sum of two integers a and b, but you are not allowed to use the operator + and -.

Example:
Given a = 1 and b = 2, return 3.


题目标签:Bit Manipulation

  这道题目让我们做两数之和,当然包括负数,而且不能用+,-等符号。所以明显是让我们从计算机的原理出发,运用OR,AND,XOR等运算法则。一开始自己想的如果两个数都是正数,那么很简单,运用XOR  ^ 去找出所有的单一的1。接着运用AND &去找出所有重复的1;重复的1就相当于carryover,需要进位。然后运动<<把重复的1给进位就可以了,最后直接OR一下就等于答案(这是错的,需要每次循环来判断新的进位)。但是发现这个是能运用于两个正数,研究来研究去,不会算带负数的,所以放弃网上找答案。

  发现答案不和我的两个正数之和算法一样嘛!唯一不同的就是答案是把算出的答案继续带回function直到carry等于0;

通过例子来看一下:

a = 5, b = 1:

a: 101

b: 001

根据我最初的算法:(错误的)

sum = a ^ b = 100

carry = a & b = 001 这里这个1就是需要进位的

carry = 001 << 1 = 010

最后把sum 100 和 carry 010 OR 一下 就等于 110 = 6。

但是答案的做法却是把sum 和 carry在带回function继续算直至carry = 0, 我们来看一下例子:

a = 5, b = 1:

a = 101

b = 001

sum = 100

carry = 010

带回

a = 100

b = 010

sum = 110

carry = 000 这里等于0了,所以结束,我的理解是,答案的做法是把carryover带回去,和sum比较,如果这一次没有继续需要进位的数字了,就可以结束,否则继续下一轮;换一句话就是,答案是把每一轮的sum和carryover拿出来,下一轮继续加一起看一看有没有新的需要进位的地方,所以明显我之前的做法是错的,我只考虑了一轮而已,实际上是每一轮都有可能有新的需要进位的地方。

那新的问题又来了,为啥负数也可以,这里的负数是2‘s complement:

比如说 -5 = 1111 1111 1111 1111 1111 1111 1111 1011

为何-5 是这样: 首先把上面的bits -1

      1111 1111 1111 1111 1111 1111 1111 1010

然后再flip一下

        0000 0000 0000 0000 0000 0000 0000 0101 = 5. 所以负数都需要先flip一下,然后+1 便成了上面那样。

带负数的两数之和,有点麻烦就是有那么多1,所以利用了自己的想象力来帮助自己理解:(不知道对不对)

举个例子:

a = -5, b = 15

把每一个sum (a) 和 carry (b) 打出来是这样的:

11111111111111111111111111111011
1111
11111111111111111111111111110100
10110
11111111111111111111111111100010
101000
11111111111111111111111111001010
1000000
11111111111111111111111110001010
10000000
11111111111111111111111100001010
100000000
11111111111111111111111000001010
1000000000
11111111111111111111110000001010
10000000000
11111111111111111111100000001010
100000000000
11111111111111111111000000001010
1000000000000
11111111111111111110000000001010
10000000000000
11111111111111111100000000001010
100000000000000
11111111111111111000000000001010
1000000000000000
11111111111111110000000000001010
10000000000000000
11111111111111100000000000001010
100000000000000000
11111111111111000000000000001010
1000000000000000000
11111111111110000000000000001010
10000000000000000000
11111111111100000000000000001010
100000000000000000000
11111111111000000000000000001010
1000000000000000000000
11111111110000000000000000001010
10000000000000000000000
11111111100000000000000000001010
100000000000000000000000
11111111000000000000000000001010
1000000000000000000000000
11111110000000000000000000001010
10000000000000000000000000
11111100000000000000000000001010
100000000000000000000000000
11111000000000000000000000001010
1000000000000000000000000000
11110000000000000000000000001010
10000000000000000000000000000
11100000000000000000000000001010
100000000000000000000000000000
11000000000000000000000000001010
1000000000000000000000000000000
10000000000000000000000000001010
10000000000000000000000000000000
1010
0
10

我们可以看到最后是10,在我理解,有负数的情况下,我们需要把负数的那些1都过滤一下,所以循环的次数会多很多,相对于正数来说。

通过上面规律,每次a都是减少它的1的数量,每次b都是增多它的0的数量,直到a的1过滤完,b的0达到极限,便结束了,得到正确答案。

利用想象力的时候到了,这就相当于a= -5 b= 15 在一个横坐标上,每一次a向右走一格,b像左走一格,或者说是负数向右走,正数向左走,直到一个最小的负数走到0,那么另外一个数就是答案。

Java Solution:

Runtime beats 9.26%

完成日期:06/27/2017

关键词:Bit Manipulation

关键点:利用xor ^ 拿到所有的单一的1;利用and &拿到所有重复的1,就是需要进位的1,利用 << 把1像左进位

  1. public class Solution
  2. {
  3. public int getSum(int a, int b)
  4. {
  5. if(b==0)
  6. return a;
  7.  
  8. int sum = a ^ b;
  9. int carry = (a & b) << 1;
  10.  
  11. return getSum(sum, carry);
  12. }
  13. }

参考资料:

http://www.cnblogs.com/grandyang/p/5631814.html

LeetCode 算法题目列表 - LeetCode Algorithms Questions List

LeetCode 371. Sum of Two Integers (两数之和)的更多相关文章

  1. [LeetCode] Sum of Two Integers 两数之和

    Calculate the sum of two integers a and b, but you are not allowed to use the operator + and -. Exam ...

  2. 371 Sum of Two Integers 两整数之和

    不使用运算符 + 和-,计算两整数a .b之和.示例:若 a = 1 ,b = 2,返回 3. 详见:https://leetcode.com/problems/sum-of-two-integers ...

  3. 剑指offer 65. 不用加减乘除做加法(Leetcode 371. Sum of Two Integers)

    剑指offer 65. 不用加减乘除做加法(Leetcode 371. Sum of Two Integers) https://leetcode.com/problems/sum-of-two-in ...

  4. LeetCode 371. Sum of Two Integers

    Calculate the sum of two integers a and b, but you are not allowed to use the operator + and -. Exam ...

  5. Leetcode 371: Sum of Two Integers(使用位运算实现)

    题目是:Calculate the sum of two integers a and b, but you are not allowed to use the operator + and -. ...

  6. LeetCode: 371 Sum of Two Integers(easy)

    题目: Calculate the sum of two integers a and b, but you are not allowed to use the operator + and -. ...

  7. [LeetCode] 633. Sum of Square Numbers 平方数之和

    Given a non-negative integer c, your task is to decide whether there're two integers a and b such th ...

  8. leetcode实践:通过链表存储两数之和

    题目: 两个 非空 的链表用来表示两个非负的整数.其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字.如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的 ...

  9. LeetCode 633. Sum of Square Numbers平方数之和 (C++)

    题目: Given a non-negative integer c, your task is to decide whether there're two integers a and b suc ...

随机推荐

  1. Java:java中BufferedReader的read()及readLine()方法的使用心得

    BufferedReader的readLine()方法是阻塞式的, 如果到达流末尾, 就返回null, 但如果client的socket末经关闭就销毁, 则会产生IO异常. 正常的方法就是使用sock ...

  2. bookStore项目总结

    感想 该项目是目前为止,我写过代码量最多的项目了-..虽然清楚是没有含金量的[跟着视频来写的],但感觉自己也在进步中-.. 写的过程中,出了不少的问题-..非常多的Servlet,JSP看得眼花-.. ...

  3. 笔记本win10安装node的尖酸历程。。。。。。

    在公司的电脑搭建vue环境分分钟搞定,周末闲的无聊给自己的电脑也搭建一个环境,谁知道这么多的问题,记录下这些问题,希望对那些安装node环境有问题的朋友一些帮助. 1.下载安装node 下载地址htt ...

  4. All about Div内显示滚动桥

    Div内显示滚动桥看似是一个简单的前端问题,然而实际会发现还是有挺多需要注意的, 本文尝试对div内显示滚动桥的各种主要实现及一些难题进行研究. 横向滚动桥 横向滚动桥比较简单,无需设置宽度,直接ov ...

  5. MySQL索引优化实例说明

    下面分别创建三张表,并分别插入1W条简单的数据用来测试,详情如下: [1] test_a 有主键但无索引   CREATE TABLE `test_a` (   `id` int(10) unsign ...

  6. Java的基本程序设计结构【2】

    注释 与大多数程序设计语言一样,Java 中的注释也不会出现在可执行程序中.因此,可以在源程序中根据需要添加任意多的注释,而不必担心可执行代码会膨胀.在Java 中,有三种书写注释的方式. 最常用的方 ...

  7. 记一次使用快速幂与Miller-Rabin的大素数生成算法

    大家都知道RSA的加密的安全性就是能够找到一个合适的大素数,而现在判断大素数的办法有许多,比如Fermat素性测试或者Miller-Rabin素性测试,而这里我用了Miller-Rabin素性测试的算 ...

  8. MVC3/4/5/6 布局页及Razor语法及Route路由配置

    一.目录结构 二.Razor语法 代码块:@{},如:@{Html.Raw(“”);} @if(){} @switch(){} @for(){} @foreach(){} @while(){} @do ...

  9. Java高新技术 JDK1.5之新特性

      Java高新技术  JDK1.5的新特性 知识概要:                 (1)静态导入 (2)可变参数 (3)增强for循环 (4)基本数据类型的自动拆箱和装箱 静态导入     ...

  10. 虚拟机+桥接模式+Host-only模式 搭建完美的Windows下Linux开发环境

    相信有很多鞋童和我一个样是一枚Linux码农(我现在还是嵌入式方向). 做Linux开发势必需要一个Linux环境, 大多数开发者会首先选择一个Linux发行版, 其中Ubuntu LTS版本应该是选 ...