《剑指offer》——二进制中1的个数
来源:互联网 发布:知乎ios源码 编辑:程序博客网 时间:2024/06/14 13:22
T:
题目描述
输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
思考:
首先要弄明白整数、负数和0在二进制中是怎么表示的。
三个概念至少要明白:
- 原码
- 反码
- 补码
这里就不多叙述,给出别人解释的相关链接:
1. http://www.360doc.com/content/12/0801/17/6828497_227700914.shtml
2. http://wenku.baidu.com/link?url=8ZlI8FKsNWj3nMk7P7dUwriLD342N6rlc2kZiaUj2XG-gGtXcRXc3ci2qKAX4_nq6m8mot0W8awgIzXmDTs3pfRgKjvD4BiYjX-qcSME5n3
对于一个正数(包括0),其二进制中1的个数很好统计,直接一步步的进行右移”>>“操作,如果右移之后的值是个奇数,即最后一位为1,那就统计,知道该数为0为止。
对于一个负数,就要相对复杂一些:
上图:
可以看到,如果还按照正数的统计方法,统计1的个数,这是个死循环,因为进行>>运算的时候,负数的最高位是补的1,1的个数永远也统计不完,而正数的最高位补的是0。
那么,反过来想:既然总位数都是32位(int类型),对于一个负数的二进制表示,能不能统计0的个数呢?
我的第一个思路就是还是沿用正数的统计方式,让负数中所有的1变为0,所有的0变为1,这样不就能统计负数中0的个数了吗?
怎么变呢?想到的一种方法是让负数与-1进行^运算,因为-1的二进制表示是32个1,进行异或,正好满足题意。
上图:
得到正数14,那就能进行正数方式的统计了,上代码:
code:
package niuke.sward2offer.numberof1; /** * T:二进制中1的个数 * * 题目描述 * 输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。 * * date: 2015.11.4 18:03 * * @author SSS * */ public class Solution { public int NumberOf1(int n) { // 标记一个数是否是负数 boolean flag = true; /** *如果是一个负数,要做的有两点: *1. 对flag进行标记 *2. 该数要和-1进行异或^ * *和-1进行异或,是因为-1的补码表示是32个1,进行异或后, *该负数的补码表示中,所有为0的位,都变为了1,就和正数一样进行1的统计, *最后还要用32减去该值,因为在n为负数的情况下,统计的是其中位数为0的个数。 */ if (n < 0) { flag = false; n = n ^ -1; } int count = 0; while (n != 0) { if (n%2 != 0) { count ++; } n = n>>1; } if (!flag) { count = 32 - count; } return count; } public static void main(String []args) { int n = 1; Solution solution = new Solution(); System.out.println(solution.NumberOf1(n)); } }
收获:
- 负数的右移>>运算,其符号位补1,而正数是补0;
- 在计算机二进制下,任意一个数 n,满足:-n = (n ^ -1) + 1
举个栗子:
负数 -22,有 -22 ^ -1 = 21
正数 9,有 9 ^ -1 = -10
升级版:
接着上面的思考,如果统计0的个数,怎么让循环结束呢?我们观察负数的>>运算,会发现,最后32位上的值都是1,那么这32个1代表的是什么数呢? 对! 是-1。所以,可以用-1作为循环结束条件。
如何判断中间0的个数呢?对于负奇数,其最后一位是1,负偶数,最后一位是0.
code:
public class Solution { public int NumberOf1(int n) { int count = 0; if (n < 0) { count = 32; while (n != -1) { if (n % 2 == 0) { count --; } n = n >> 1; } return count; } while (n > 0) { if (n % 2 != 0) { count ++; } n >>= 1; } return count; } }
讨论版里看到的神级代码,确实没想到这么去做…
- 《剑指offer》——二进制中1的个数
- 剑指offer——二进制中1的个数
- 剑指offer——二进制中1的个数
- 剑指offer——二进制中1的个数
- 二进制中1的个数——剑指offer
- 剑指offer——二进制中1的个数
- 剑指offer——二进制中1的个数
- 剑指offer——二进制中1的个数
- 剑指offer——二进制中1的个数
- 剑指offer——11.二进制中1的个数
- 剑指Offer—11—二进制中1的个数
- 剑指offer—二进制中1的个数
- 剑指offer—二进制中1的个数
- 《剑指offer》—11、二进制中1的个数
- 剑指offer(11)—二进制中1的个数
- 剑指offer—二进制中1的个数
- 剑指offer—二进制中1的个数
- 剑指offer:二进制中1的个数
- 欢迎使用CSDN-markdown编辑器
- 发现翻-强的一个不错的选择,感觉不不错,分享
- java中Map和List初始化的两种方法
- 黑马程序员—Java基础—IO3
- SparkSQL(二)
- 《剑指offer》——二进制中1的个数
- HDU 5534 Partial Tree(完全背包)
- Invert Binary Tree
- html页面之间传递值
- JAVA中接口和抽象类的区别
- HDU 2650 判断是a+bj 是否为高斯素数
- python的列表(List),元组(Tuple),集合(Set),字典(Dict)
- C# Listview 控件 加 button按钮的实现
- 设计模式学习笔记--命令模式