程序员面试金典: 9.5位操作 5.5编写一个函数,确定需要改变几个位,才能将整数A转成整数B

#include <iostream>
#include <stdio.h>
#include <string>

using namespace std;

/*
问题:编写一个函数,确定需要改变几个位,才能将整数A转成整数B。
问题:这个好像记得需要用到 ( n & (n-1)) == 0。
      找规律: A: 1011 , B:1101 , 那么需要变换两次, 将两个整数进行异或处理。
	  1011
	  1101
异或: 0110
两数异或后的结果,然后统计1的个数即可
那么问题转化为如何统计1个整数中1的个数,设这个整数为num:
用 num & 1 == 1来判断,然后令 num >>= 1(向右移动),直到num变为0,这个时间复杂度为O(n),n为整数的二进制长度
如果用 ( num & (num-1) ) != 0,就累加1个个数,则时间复杂杜伟O(k),k为该整数中1的个数,
之所以: num & (num-1),并且后续循环令num = num & (num -1),是因为这样每次会消去最低位的1

输入:
1011 1101
1011 0101
1111 1111
输出:
2
3
0

关键:
1 两数异或后的结果,然后统计1的个数即可
那么问题转化为如何统计1个整数中1的个数,设这个整数为num:
用 num & 1 == 1来判断,然后令 num >>= 1(向右移动),直到num变为0,这个时间复杂度为O(n),n为整数的二进制长度
2 如果用 ( num & (num-1) ) != 0,就累加1个个数,则时间复杂度为O(k),k为该整数中1的个数,
之所以: num & (num-1),并且后续循环令num = num & (num -1),是因为这样每次会消去最低位的1,
通过不断翻转最低有效位,计算多少次c才会变成0,操作c=c & (c-1)会清除c的最低有效位
*/

typedef struct Result
{
	Result(){}
	Result(const Result& other){ *this = other; }
	Result(bool isResult , int result):_isResult(isResult) , _result(result){}
	bool _isResult;
	int _result;
}Result;

Result toTenRadix(string& sNum)
{
	if(sNum.empty())
	{
		return Result(false,-1);
	}
	//字符串逆序遍历,累加即可
	int sum = 0;
	int size = sNum.size();
	int value = 0;
	int count = 0;
	for(int i = size - 1 ; i >= 0 ; i--)
	{
		if( '0' <= sNum[i] && sNum[i] <= '9')
		{
			value = sNum[i] - '0';
			sum += value * ( (int) pow(2 , count));
		}
		else
		{
			return Result(false , -1);
		}
		count++;
	}
	return Result(true, sum);
}

int count1(int num)
{
	if(0 == num)
	{
		return 0;
	}
	int count = 0;
	while( ( num & (num-1)) != 0 )
	{
		count++;
		num &= (num - 1);
	}
	count++; //最后一次退出一定是因为相与为0,此时包含1个1,需要累加
}

int getChangeTimes(int numA , int numB)
{
	int resultNum = numA ^ numB;
	//统计1的个数
	int count = count1(resultNum);
	return count;
}

void process()
{
	string sA , sB;
	Result A, B;
	int times = 0;
	while(cin >> sA >> sB)
	{
		//转换为十进制
		A = toTenRadix(sA);
		B = toTenRadix(sB);
		//接下来统计
		times = getChangeTimes(A._result , B._result);
		cout << times << endl;
	}
}

int main(int argc , char* argv[])
{
	process();
	getchar();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值