#数据结构与算法学习笔记#剑指Offer10:位运算:求二进制中1的个数+四种解法比较+测试用例(Java、C++)

2018.8.6

一开始看到这道题不假思索地转了个字符串然后通过了。

后来参考其他优秀代码才发现是考位运算,年轻了年轻了。

比较四种解法:

1.转换为二进制字符串对字符‘1’的个数进行计算:比较投机取巧,但是比较通用,尤其在涉及大数运算的时候。

2.二进制从右向左移位并&1:初看简洁方便,但是在输入负数的时候会陷入死循环。

3.将1从左向右移位并和原数比较:正解,不会陷入死循环。

4.原数减1再和原整数相&,会把整数最右边的一个1变成0,计算原数变成0的运算次数:正解,思维比较出彩。


题目描述

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


JAVA实现:

/**
 * 
 * @author ChopinXBP 输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
 *         思路:Integer.toBinaryString(n)转为字符串判断
 *
 */

public class NumberOf1_11 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int n = Solve(-5);
		System.out.println(n);
	}

	// -------------投机取巧的解法:转换为字符串---------------------//
	public static int Solve(int n) {

		int result = 0;
		String binstr = Integer.toBinaryString(n);
		System.out.println(binstr);

		for (int i = 0; i < binstr.length(); i++) {
			if (binstr.charAt(i) == '1')
				result++;
		}

		return result;
	}

	// -------------可能陷入死循环的解法:从右向左移---------------------//
	// 从n的2进制形式的最右边开始判断是不是1,该解法如果输入时负数会陷入死循环,因为负数右移时,在最高位补得是1,最后会补成0xFFFFFFFF。 

	public static int NumberOf1_CanNotUse(int n) {
		int count = 0;
		while (n != 0) {
			// 用1和n进行位与运算,结果要是为1则n的2进制形式.最右边那位肯定是1,否则为0
			if ((n & 1) == 1) {
				count++;
			}
			// 把n的2进制形式往右推一位
			n = n >> 1;
		}
		return count;
	}

	// --------------------正解:从左向右移---------------------------//
	// 思想:用1(1自身左移运算,其实后来就不是1了)和n的每位进行位与,来判断1的个数

	private static int NumberOf1_low(int n) {
		int count = 0;
		int flag = 1;
		while (flag != 0) {
			if ((n & flag) != 0) {
				count++;
			}
			flag = flag << 1;
		}
		return count;
	}

	// ---------------------------最优解----------------------------//
	// 思想:把一个整数减去1,再和原整数做与运算,会把整数最右边的一个1变成0。
	// 那么一个整数的二进制表示中有多少个1,就可以进行多少次这样的操作。

	public static int NumberOf1(int n) {
		int count = 0;
		while (n != 0) {
			++count;
			n = (n - 1) & n;
		}
		return count;
	}

}

C++实现示例:

#include "stdafx.h"

int NumberOf1_Solution1(int n)
{
    int count = 0;
    unsigned int flag = 1;
    while(flag)
    {
        if(n & flag)
            count ++;

        flag = flag << 1;
    }

    return count;
}

int NumberOf1_Solution2(int n)
{
    int count = 0;

    while (n)
    {
        ++ count;
        n = (n - 1) & n;
    }

    return count;
}

测试代码:


void Test(int number, unsigned int expected)
{
    int actual = NumberOf1_Solution1(number);
    if(actual == expected)
        printf("Solution1: Test for %p passed.\n", number);
    else
        printf("Solution1: Test for %p failed.\n", number);

    actual = NumberOf1_Solution2(number);
    if(actual == expected)
        printf("Solution2: Test for %p passed.\n", number);
    else
        printf("Solution2: Test for %p failed.\n", number);

    printf("\n");
}

int _tmain(int argc, _TCHAR* argv[])
{
    // 输入0,期待的输出是0
    Test(0, 0);

    // 输入1,期待的输出是1
    Test(1, 1);

    // 输入10,期待的输出是2
    Test(10, 2);

    // 输入0x7FFFFFFF,期待的输出是31
    Test(0x7FFFFFFF, 31);

    // 输入0xFFFFFFFF(负数),期待的输出是32
    Test(0xFFFFFFFF, 32);

    // 输入0x80000000(负数),期待的输出是1
    Test(0x80000000, 1);

    return 0;
}


#Coding一小时,Copying一秒钟。留个言点个赞呗,谢谢你#

猜你喜欢

转载自blog.csdn.net/qq_20304723/article/details/81455021