二进制中1的个数问题

·  阅读 237

小知识,大挑战!本文正在参与「程序员必备小知识」创作活动。

问题

请实现一个函数,输入一个整数,输出该数二进制表示中 1 的个数。例如把9表示成二进制是1001,有2位是1。因此如果输入9,该函数输出2。

力扣链接

leetcode-cn.com/problems/er…

考察要点

对于位运算&, |, ~, ^的理解

对于二进制的理解

思路1

判断整数的最后一位是不是1, 可用用 n%1! = 0来判断, 也可以用n & 1 != 0来判断, 如果是1, 则记录下1的个数

然后将n右移1位, 也就是n >> 1, 然后继续判断最后一位是否为1, 直到最后为0

缺点:

  1. 不能对负整数进行1的个数的统计, 因此如果负整数的话, 将该数右移, 前面会补1, 而不是0
  2. 这样做还会更改原来n的值, 也不是一个好的方法

代码1

 public int hammingWeight(int n) {
     // 用来记录1的个数
     int res = 0;
     while (n != 0) {
         // 如果最后一位是1, 则记录1的个数
         if ((n & 1) != 0) res++;
         
         // 将整数右移一位
         n >>= 1;
     }
 ​
     return res;
 }
复制代码

思路2

基于思路1, 要对目标值进行右移. 我们可以转换思想, 对1进行左移, 然后按位&进行个数的统计

例如: 1在第0位, 进行n & 1 != 0判断, 如果该位为1, 则进行1的个数记录

然后将1 <<= 1, 进行判断; 然后1 <<= 2进行判断, 依此类推.

代码2

 public int hammingWeight(int n) {
     // 用来记录1的个数
     int res = 0;
     for (int i = 0; i < 32; i++) {
         // 将1进行左移, 进行1的个数统计并记录
         if ((n & (1 << i)) != 0) res++;
     }
 ​
     return res;
 }
复制代码

思路3

在一个数n不等于0的情况下

如果n & (n - 1) , 那么它的值就是将n的最右边一个1变成0

例如: 二进制数1100和它减去1的数1011进行运算, 也就是1100 & 1011 = 1000

按照这样的思路, 就会减少运算次数, 也就是一个数的二进制位中, 它有多少个1, 就进行多少次运算

代码3

 public int numsOfOne3(int n) {
     // 用来记录1的个数
     int res = 0;
     while (n != 0) {
         // 只要n不等于0, 那么它的二进制位中必有一个1
         res++;
         
         // 将二进制位中最右边的1变为0
         n &= (n - 1);
     }
     return res;
 }
复制代码

总结

通过本题可以加深我们对于二进制数及位运算的理解程度. 还可以学到对于设计到二进制算法时, 去解题的技巧及思路.

把一个整数和将这个整数减去1的整数进行按位与运算, 得到的结果是将该整数二进制位中最右边的1变为0.

分类:
后端
收藏成功!
已添加到「」, 点击更改