剑指offer-面试题15:二进制中1的个数 解法+java移位运算符介绍

题目描述

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

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

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

位运算解法

本题考查位运算知识。我们将二进制串n的最后一位和1做“与”运算,若结果为1,表示最后一位是1,则统计结果加1;若“与”运算为0,则表示最后一位是0;“与”运算后将二进制串向右做一次移位操作,使得原来的倒数第二位处于最后一位,再循环进行“与”运算,直到n=0为止。
下面是位运算解法代码:

public class Solution {
    // you need to treat n as an unsigned value
    public int hammingWeight(int n)
    {
        int count=0; //统计1的个数
        while(n!=0)
        {
            count+=(n&1);
            n=n>>>1;//注意采用无符号右移
        }
        return count;
    }
}

在输入的二进制串长度为n的情况下
时间复杂度:共需要进行n此比较和n-1此移位,O(n)
空间复杂度:O(1)

需要注意的点:

  1. 本题已经在注释中假设给定的二进制串都是无符号数,因此最左边位保存的应看做数值而非符号。在Java中,如果二进制串有符号,正数的最左一位是0,表示正号,右移时高位补0,不会发生错误;负数的最左一位是1,表示符号,右移时会在高位补1,最终使得二进制串全为1,陷入死循环

正数右移位(java中正数用原码表示):

位移前:10  位移后:2
00000000 00000000 00000000 00001010>>2=00000000 00000000 00000000 00000010

负数右移位(java中负数用补码表示):

位移前:-6  位移后:-2 
11111111 11111111 11111111 11111010>>2=11111111 11111111 11111111 11111110

因此我们右移时要注意使用“>>>”,即无符号右移位符号,无符号右移时高位补0,不会发生错误。
负数无符号右移位(java中负数用补码表示):

位移前:-1  位移后:1073741823
11111111 11111111 11111111 11111111>>>2=00111111 11111111 11111111 11111111
  1. LeetCode中给出的输入示例如:00000000000000000000000000001011并不符合规范。在Java中数值的二进制串的正确表示方法应该是0b,十六进制和八进制表示方法分别为:0x0。例如:
    0b00101=5(十进制)
    0000101=65(十进制)
    0x00101=257(十进制)

你可能感兴趣的:(剑指offer-面试题15:二进制中1的个数 解法+java移位运算符介绍)