LeeCode 191. 位1的个数 引发的位运算与二进制的思考

题目要求:

      编写一个函数,输入是一个无符号整数,返回其二进制表达式中数字位数为 ‘1’ 的个数(也被称为汉明重量)。

示例 1:

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

1.刚开始想到的最简单的办法肯定就是,先将输入的int n转换为二进制形式字符串,然后挨个计算其中的‘1’的个数

//调用Integer函数
    public static int hammingWeight(int n) {
        String s = Integer.toUnsignedString(n, 2);
//        System.out.println(s);
        int len = s.length(), count = 0;
        for(int i = 0; i < len; i++){
            if(s.charAt(i) == '1')
                count++;
        }
        return count;
    }

这是一种办法,但是耗时稍微长一点。

转化为二进制的时候使用了Integer库的函数,toUnsignedString(int n, radix 2)

  • public static String toUnsignedString(int i, int radix)
    • 以第二个参数指定的基数中的无符号整数值返回第一个参数的字符串表示形式。
    • 如果基数小于Character.MIN_RADIX或大于Character.MAX_RADIX ,则使用基数10
    • 请注意,由于第一个参数被视为无符号值,因此不会打印前导符号。

 

2.又想了如果不使用自带函数呢,利用二进制的定义去进行转换

//利用除法和取余计算二进制
    public static int hammingWeightDivide(int n) {
        StringBuilder sb = new StringBuilder();
        while (n > 0){
            sb.insert(0, String.valueOf(n % 2));
            n = n / 2;
        }
        int len = sb.length(), count = 0;
        for(int i = 0; i < len; i++){
            if(sb.charAt(i) == '1')
                count++;
        }
        return count;
    }

 

3.最后一种就是位运算:

    //位运算,  每一位都与1做“&”运算,都为1,结果才为1,可以进行判断
    //需要注意的一个点就是位运算的优先级比较低,需要加上括号
    // 第一步     111111010101001010       n
    //           000000000000000001       mask
    // 第二步     111111010101001010       n
    //            000000000000000010      mask

    public static int hammingWeightWei(int n) {
        int count = 0;
        int mask = 1;
        for(int i = 0; i < 32; i++){
            if((n & mask) != 0)
                count++;
            //将掩码左移一位,与下一位作比较
            mask <<= 1;
        }
        return count;
    }

位运算中的’&‘运算,计算方法是 

如果相对应位都是1,则结果为1,否则为0

这里刚好用来做计算’1‘的个数,每一次都int n的一位与1做与运算,如果结果不为0,那么就代表该位上的数字是’1‘;count++

之后再将mask中1的位置往左移,利用按位左移运算符可以达到这个效果,接着继续计算n的后位。

 

4.接着衍生出了一个新的想法,如果需要将一个无符号位的数转换成指定位数的二进制形式(不足的位取0)

例: 4的二进制形式是 0100,那么如果函数指定需要6位数的二进制形式,那么返回结果就是 000100

/**
     * 将一个int数字转换为二进制的字符串形式。
     * @param num 需要转换的int类型数据
     * @param index要转换的二进制位数,位数不足则在前面补0
     * @return 二进制的字符串形式
     */
    public static String toBinary(int num, int index) {
        int value = 1 << index| num;
        System.out.println(value);
        String bs = Integer.toBinaryString(value); // 将value转换为二进制形式的字符串
        //将最前面的1去掉
        return  bs.substring(1);
    }

这里解释一下, 1 利用按位左移运算符, 1 << index, 假设 digits等于6, 那么原来1的二进制形式是 0000001,按位左移之后就变成了1000000,这个时候再将按位左移之后的结果与num做’或‘运算, “|"运算符的计算方法是,

如果相对应位都是 0,则结果为 0,否则为 1

那么1000000

       0000100    结果为 1000100

最后舍去字符串前面的第一位,结果就是  000100,让结果确定为6位数。

 

有符号位和无符号位

无符号数中,所有的位都用于直接表示该值的大小

有符号数中,第一位用来表示正负,后面的位才用来表示大小

比如一个无符号数   1111 0001  代表数值 241     而有符号数 1111 0001  -113

即有符号数第一位, 1代表“-”, 0 代表“+”;

但是java的基本数据类型都是有符号数,

byte、short、char、double、int、long、float都是有符号数

 

你可能感兴趣的:(java,java)