当前位置:  首页>> 技术小册>> 数据结构与算法(下)

题目描述

输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。

解法

解法一

利用整数 1,依次左移每次与 n 进行与运算,若结果不为0,说明这一位上数字为 1,++cnt。

此解法 i 需要左移 32 次。

不要用 n 去右移并与 1 进行与运算,因为n 可能为负数,右移时会陷入死循环。

  1. public class Solution {
  2. public int NumberOf1(int n) {
  3. int cnt = 0;
  4. int i = 1;
  5. while (i != 0) {
  6. if ((n & i) != 0) {
  7. ++cnt;
  8. }
  9. i <<= 1;
  10. }
  11. return cnt;
  12. }
  13. }

解法二(推荐)

  • 运算 (n - 1) & n,直至 n 为 0。运算的次数即为 n 的二进制中 1 的个数。

因为 n-1 会将 n 的最右边一位 1 改为 0,如果右边还有 0,则所有 0 都会变成 1。结果与 n 进行与运算,会去除掉最右边的一个1。

举个栗子:

  1. n = 1100
  2. n - 1 = 1011
  3. n & (n - 1) = 1000
  4. 即:把最右边的 1 变成了 0

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

  1. /**
  2. * @author bingo
  3. * @since 2018/11/20
  4. */
  5. public class Solution {
  6. /**
  7. * 计算整数的二进制表示里1的个数
  8. * @param n 整数
  9. * @return 1的个数
  10. */
  11. public int NumberOf1(int n) {
  12. int cnt = 0;
  13. while (n != 0) {
  14. n = (n - 1 ) & n;
  15. ++cnt;
  16. }
  17. return cnt;
  18. }
  19. }

测试用例

  1. 正数(包括边界值 1、0x7FFFFFFF);
  2. 负数(包括边界值 0x80000000、0xFFFFFFFF);
  3. 0。

该分类下的相关小册推荐: