剑指offer2之二进制中的1

前言

位运算是把数字用二进制表示之后,对每一位上 0 或 1 的运算。二进制及其位运算非常重要,在很多底层技术中频繁出现。那么面试题更不例外了。

位运算总共有 5 种运算,与、或、异或、左移和右移。关于与 (&)、或 (|)和异或 (\(\oplus\)) 的规律可总结为:

  1. 与:只要有 0就是 0,否则为 1;
  2. 或:只要有 1 就是 1,否则为 0;
  3. 异或:两个二进制位不同为 1,相同为 0。

左移运算符 m<>n,表示把 m 右移 n 位。若为负数,则高位补 0,否则高位补 1。

题目(二进制中1的个数)

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

算法思路

算法思路一

我们把输入的二进制数的最后一位与 1 进行位与运算,如果是 1,就计数;然后将二进制数右移一位,再进行同样的操作,直到整数为 0 退出循环。此思路只能针对输入的整数是正整数,否则会陷入死循环。

算法思路二

由于正数和负数的二进制数 n 移位规律不同,因此采用右移来计数较为麻烦。那现在我们就不移动输入整数的二进制表示,而是利用一个无符号的数 1,然后先和 n 的最低位相与,判断最低位是否为 1;然后接着把 1 左移一位,再和 n 做与运算,就能判断 n 的次低位是不是1,这样一直操作,直到循环 n 的二进制位数次。

算法思路三

我们发现将 n 减去 1 再和 n 位与可以去掉 n 中最右的 1,那么 n 中有几个这样的 1 ,就需要去掉几次。

注:把一个整数减去 1 之后再和原来的整数做位与运算,得到的结果相当于把整数的二进制表示中最右边的 1 变成 0。很多二进制的问题都可以用这种思路解决。

算法实现

算法实现一

算法实现二

算法实现三

复杂度分析

算法一的时间主要消耗在对二进制的移位上,时间复杂度为 O(logn);算法二需要进行循环 n 次(输入的二进制有 n 位),因此时间复杂度为 O(n);若输入数的二进制表示中 1 的个数为 n,那么算法三仅需循环 n 次,时间复杂度最好达到 O(1),最坏达到 O(n)。另外空间复杂度均为 O(1)。

参考

<<剑指offer2>>

-------------本文结束感谢您的阅读-------------