整数的二进制表示中有多少个1的问题
2015-07-11 01:15
253 查看
我在剑指offer上面看到这道题,看到这道题是用c++写的,但是我用java编写的时候遇到问题。
首先描述问题:
一个整数(可以为整数也可以为负数),它的二进制表示中有多少个1,。
这道题有三道解法。
1.解法一:
就是右移这个数,然后与1进行按位与的运算,如果是1的话,那么技术器就加1,但是如果是负数的话,因为符号位是1,所以一直向右移动的话,高位就会一直补1,所以就会进入死循环,所以要进行绝对值的处理。下面是我的代码:
2.解法二:
这种方法的思路就是让1往左移,如果每次与操作数按位相与得出的是0,那么计数器就加一,我遇到的问题就出现在这里,如10的1的个数应该是2,而-10中1的个数应该是3,因为有一个符号位,如果不加符号处理话,那么得出数应该是30,也就是有30个1,这就是与剑指offer上矛盾的地方,后来我分析原因是这样的,程序中我让左移停止的条件是,两个数相与为0就停止,因为一个整数是32位,而10应该是11111111111111111111111111111010,所以得出应该是30,所以按照剑指offer上的思路,用java是得不出正确结果的,所以还需要加符号处理,以下为我这种算法的代码:
3.解法三:
这种解法是最巧妙的能够解决很多衍生的问题,这些问题在后面说,先解释我的算法,当然也是在处理符号后,因为按照剑指offer的话对于10和-10,还是会得出2和30的结果,在符号处理之后,那么试想,一个数减去1后,是不是就会把最右端的1变成0,那么n&n-1就会连同最后一位1和之后的数据位都清零,所以说,减一次就能得出一个1,也就数有多少1,就操作几次,所以这种算法的效率最高,下面是我java的代码:
写这么多就是想把我遇到的问题和大家分享,不知道大家遇到类似问题没,运用第三种解法还可以解决好多衍伸的问题,例如判断一个数是不是2的幂,因为如果是2的幂的话,那么就只有一个1,所以只需操作一次如果为0那么就是2的幂次方,再如,判断两个整数有多少位是不同的,涉及到不同那么我们必然会想到亦或,不同位亦或后肯定为1,所以又转换成求整数1的个数问题,所以第三种解法应该是比较优秀的 。这是我的一点学习心得,写的太晚了该睡了,祝大家好运连连啊。
首先描述问题:
一个整数(可以为整数也可以为负数),它的二进制表示中有多少个1,。
这道题有三道解法。
1.解法一:
就是右移这个数,然后与1进行按位与的运算,如果是1的话,那么技术器就加1,但是如果是负数的话,因为符号位是1,所以一直向右移动的话,高位就会一直补1,所以就会进入死循环,所以要进行绝对值的处理。下面是我的代码:
/** * 这种方法是通过右移操作数实现的,但是如果是负数的话,由于符号位是1,所以会出现死循环的结局,所以 * 这种方法不可取 * @param n * @return */ public static int test1(int n){ int count=n>=0?0:1; n=Math.abs(n); int tag=1; while(n!=0){ if((n&tag)==1){ count++; } n=n>>1; } return count; }
2.解法二:
这种方法的思路就是让1往左移,如果每次与操作数按位相与得出的是0,那么计数器就加一,我遇到的问题就出现在这里,如10的1的个数应该是2,而-10中1的个数应该是3,因为有一个符号位,如果不加符号处理话,那么得出数应该是30,也就是有30个1,这就是与剑指offer上矛盾的地方,后来我分析原因是这样的,程序中我让左移停止的条件是,两个数相与为0就停止,因为一个整数是32位,而10应该是11111111111111111111111111111010,所以得出应该是30,所以按照剑指offer上的思路,用java是得不出正确结果的,所以还需要加符号处理,以下为我这种算法的代码:
/** * 这种方法虽然不会引起死循环但是还是效率不高 * @param n * @return */ public static int test2(int n){ int count=n>=0?0:1; int tag=1; while(Math.abs(n)>=tag){ if((n&tag)==0){ count++; } tag=tag<<1; } return count; }
3.解法三:
这种解法是最巧妙的能够解决很多衍生的问题,这些问题在后面说,先解释我的算法,当然也是在处理符号后,因为按照剑指offer的话对于10和-10,还是会得出2和30的结果,在符号处理之后,那么试想,一个数减去1后,是不是就会把最右端的1变成0,那么n&n-1就会连同最后一位1和之后的数据位都清零,所以说,减一次就能得出一个1,也就数有多少1,就操作几次,所以这种算法的效率最高,下面是我java的代码:
/** * 这种算法是每次减去1就会使原来数字最左方的1变为0所以知道全变为0为止 * @param n * @return */ public static int test3(int n){ int count=n>=0?0:1; n=Math.abs(n); while(n!=0){ count++; n=n&(n-1); } return count; } public static void main(String[] args) { //System.out.println(test1(-10)); //System.out.println(test2(-10)); System.out.println(test3(-10)); }
写这么多就是想把我遇到的问题和大家分享,不知道大家遇到类似问题没,运用第三种解法还可以解决好多衍伸的问题,例如判断一个数是不是2的幂,因为如果是2的幂的话,那么就只有一个1,所以只需操作一次如果为0那么就是2的幂次方,再如,判断两个整数有多少位是不同的,涉及到不同那么我们必然会想到亦或,不同位亦或后肯定为1,所以又转换成求整数1的个数问题,所以第三种解法应该是比较优秀的 。这是我的一点学习心得,写的太晚了该睡了,祝大家好运连连啊。
相关文章推荐
- Leetcode23-Merge k Sorted Lists
- linux分区和文件系统
- 同位语
- shell编程技术之-基础知识
- 各种递归算法化简(化复杂)的方法和案例
- UVA 111 History Grading(最长公共子序列dp)
- centos 7 启动tomcat服务
- POJ 2762 tarjan缩点+并查集+度数
- Ecmascript-262-3 in detail. Chapter 4. Scope chain.
- servlet
- display:none与visible:hidden的区别
- 黑马程序员-IOS学习笔记 C语言编程时常犯十八个错误
- Swift语言 OS X程序点击dock图标重新弹出窗口方法
- MySql 如果字段为NULL则返回0
- sql 中的NULL小问题 ,大bug
- 黑马程序员-IOS学习笔记 Xcode注释自动生成
- delphi 遍历所有文件夹
- 作用域链(Scope Chain)
- Java自学笔记(Java自学教程/带示意图) - 罗函
- 【数据结构之树状数组】