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

原创 2017年01月03日 21:44:13
#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;
}

32位机器下面各类型的取值范围(sizeof值)

32位机器下面各类型的取值范围(sizeof值)   32位机器下面的结果:  数据类型 说明 字节数 取值范围 bool...

面试题——a、b交换与比较

面试题1: 有两个变量a和b,不用“if”,"?"、"switch"或其他判断语句,找出两个数中间比较大的 方案一: int  max = ((a+b)+abs(a-b))/2 注:abs()...

程序员面试金典: 9.5位操作 5.7寻找丢失的整数

#include #include #include #include using namespace std; /* 问题:数组A包含0到n的所有整数,但其中缺了一个。在这个问题中,只用...

程序员面试金典: 9.5位操作5.2对一个浮点数,打印它的二进制表示

#include #include #include #include using namespace std; /* 问题:给定一个介于0和1之间的实数(如0.72),类型为double...

程序员面试金典——解题总结: 9.18高难度题 18.3编写一个方法,从大小为n的数组中随机选出m个整数。要求每个元素被选中的概率相同。

#include #include #include using namespace std; /* 问题:编写一个方法,从大小为n的数组中随机选出m个整数。要求每个元素被选中的概率相同。 分...

程序员面试金典: 9.5位操作 5.8通过位操作进行两点连线

#include #include #include #include #include using namespace std; /* 问题:有个单色屏幕存储在一个一维字节数组中,使得...

程序员面试金典——解题总结: 9.17中等难题 17.12设计一个算法,找出数组中两数之和为指定值的所有整数对。

#include #include #include #include using namespace std; /* 问题:设计一个算法,找出数组中两数之和为指定值的所有整数对。 分析:...

程序员面试金典——解题总结: 9.17中等难题 17.8给定一个整数数组(有正数有负数),找出总和最大的连续数列,并返回总和

#include #include #include using namespace std; /* 问题:给定一个整数数组(有正数有负数),找出总和最大的连续数列,并返回总和 分析:这个是...

编写一个能将给定非负整数列表中的数字排列成最大数字的函数。

//编写一个能将给定非负整数列表中的数字排列成最大数字的函数。例如,给定[50,2,1,9],最大数字为95021。 public class Test4{ public static void m...

编写一个能将给定非负整数列表中的数字排列成最大数字的函数

编写一个能将给定非负整数列表中的数字排列成最大数字的函数。例如,给定[50,2,1,9],最大数字为95021。 public class TestFindMaxNum { /** * ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:程序员面试金典: 9.5位操作 5.5编写一个函数,确定需要改变几个位,才能将整数A转成整数B
举报原因:
原因补充:

(最多只允许输入30个字)