更多2019年的技术文章,欢迎关注我的微信公众号:码不停蹄的小鼠松(微信号:busy_squirrel),也可扫下方二维码关注获取最新文章哦~
T:
题目描述
输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
思考:
首先要弄明白整数、负数和0在二进制中是怎么表示的。
三个概念至少要明白:
- 原码
- 反码
- 补码
这里就不多叙述,给出别人解释的相关链接:
- http://www.360doc.com/content/12/0801/17/6828497_227700914.shtml
- 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;
}
}
讨论版里看到的神级代码,确实没想到这么去做…
更多2019年的技术文章,欢迎关注我的微信公众号:码不停蹄的小鼠松(微信号:busy_squirrel),也可扫下方二维码关注获取最新文章哦~