[剑指-Offer] 15. 二进制中1的个数(位运算、技巧、代码优化)

1. 题目来源

链接:二进制中1的个数
来源:LeetCode——《剑指-Offer》专项

2. 题目说明

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

示例1 :

输入:00000000000000000000000000001011
输出:3
解释:输入的二进制串 00000000000000000000000000001011 中,共有三位为 ‘1’。

示例 2:

输入:00000000000000000000000010000000
输出:1
解释:输入的二进制串 00000000000000000000000010000000 中,共有一位为 ‘1’。

示例 3:

输入:11111111111111111111111111111101
输出:31
解释:输入的二进制串 11111111111111111111111111111101 中,共有 31 位为 ‘1’。

3. 题目解析

方法一:常规左移、右移位运算解法

题意很明确的一道位运算问题,首先普及两个知识点:

  1. 正数右移运算,会在最高位补 0,而负数右移运算,会给最高位补 1,也就是补符号位。常见的解法如果将数字 n,循环右移并 & 1,当 n 变化为 0 时,循环结束。很明显,这个只有当 n 为正数才适用,负数会构成死循环
  2. 左移运算就在末尾补零即可,这个不区别正负数

解决负数死循环问题,可以将 1 循环左移并 &n 即可。

下面是些别名:

typedef  unsigned  char  uchar;
typedef  uchar  uint8;
typedef   uint8  TFlowPortId;
typedef  unsigned  short  ushort;
typedef  ushort  uint16;
typedef  uint16  TFlowNodeId;
typedef  unsigned  int   uint;
typedef  uint  uint32;

参见代码如下:

// 执行用时 :0 ms, 在所有 C++ 提交中击败了100.00%的用户
// 内存消耗 :8.1 MB, 在所有 C++ 提交中击败了100.00%的用户

class Solution {
public:
    int hammingWeight(uint32_t n) {
        int count = 0;
        uint32_t flag = 1;
        while (flag) {
            if (n & flag)
                count++;
            flag = flag << 1;
        }
        return count;
    }
};

在这个人觉得采用 while(flag) 进行判断不够明确,采用 for 进行 32 次即可。

方法二:位运算技巧

n = n & (n -1) 相当于把整数的二进制表示中最右边的 1 变成 0。很多二进制都可以用这个思路解决。

参见代码如下:

// 执行用时 :4 ms, 在所有 C++ 提交中击败了73.72%的用户
// 内存消耗 :8.2 MB, 在所有 C++ 提交中击败了100.00%的用户

class Solution {
public:
    int hammingWeight(uint32_t n) {
        int count = 0;
        while (n) {
            n = n & (n - 1);
            ++count;
        }
        return count;
    }
};

方法三:位运算常见问题总结

位运算问题真的考智商,这个需要多多积累吧,尤其第二种方法很常见的。在此再给列出《剑指-Offer》中常见的位运算问题,做以复习:

  1. 用一条语句判断一个整数是不是 2 的整数次方。一个整数如果为 2 的整数次方,那么它的二进制表示中有且仅有 1 位是 1,而其它所有位均为 0。采用方法二n = n & (n -1),一步搞定!
  2. 输入两个整数 m 和 n,计算需要改变 m 的二进制表示中的多少位才能得到 n。这个问题也很常见,好像 LeetCode 周赛就有一个相当类似的问题。第一步:求两个数的异或。第二步:统计异或结果中 1 的位数。 搞定!
发布了307 篇原创文章 · 获赞 125 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/yl_puyu/article/details/104501967