二进制中1的个数
二进制中1的个数
https://www.nowcoder.com/practice/8ee967e43c2c4ec193b040ea7fbb10b8?tpId=13&&tqId=11164&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking
数学类的题目就是技巧性太强,而且属于知识点型的,知道就很简单,不知道就一点都不知道怎么下手。
自己想了一个思路,与1进行按位与,结果为1时计数加1,然后把数值一次向右移1位,这样计算,结果只能针对正整数,因为负数的右移左端补的是1.
还是看了题解才想明白。
解法一、将掩码左移
即用0b1
作为掩码,不是将原数值n依次右移(避免负数问题),而是将掩码依次左移:
public class Solution { public int NumberOf1(int n) { int count = 0; int mark = 0b1; while (mark != 0) { if ((n & mark) != 0) { count++; } mark <<= 1; } return count; } }
这个地方涉及到一个Java的语言特性:如果我们直接将0b1
左移超过该类型的最大位数,这里即int
类型的32位,那么编译器将直接对左移的次数按该类型的最大位数取余,也就是说我们如果指定0b1 << 33
,实际上编译器处理后,变成了0b1 << 1
.
而如果我们将数值一次向左移动一位,移动33次,则编译器不会进行处理,而最终得到的将是0.
解法二
数值n和n-1做按位与运算的结果等于消除n的二进制表示中最右侧的1,这个知识点了解后就非常巧妙。
public class Solution { public int NumberOf1(int n) { int count = 0; while (n != 0) { n = n & (n - 1); count++; } return count; } }