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

原创 2017年01月04日 01:15:13
#include <iostream>
#include <stdio.h>
#include <bitset>
#include <vector>

using namespace std;

/*
问题:数组A包含0到n的所有整数,但其中缺了一个。在这个问题中,只用一次操作无法取得数组A里某个整数的完整内容。
      此外,数组A的元素皆以二进制表示,唯一可用的访问操作是“从A[i]取出第j位数据”,该操作的时间复杂度为长度。
	  请编写代码找出那个缺失的整数。你有办法在O(n)时间内完成吗?
分析:
书上解法:通过分析最低有效位(若指定最低有效位为1,则表明每个整数的最后一位上的数字)中1和0的数字结果来确定。
          参见。程序员面试金典:P172页。
		  假设: 0000, 0001, 0010
		  观察发现:如果n为奇数,则在最低有效位为1时,count(0)=count(1);n为偶数,count(0) = count(1) + 1
		  规律: count(0) >= count(1)
		  如果除去丢失的整数,统计的某最低有效位: count(0) <= count(1),则说明该丢失的整数的该最低有效位应该为0
		                                           count(0) > count(1),  则说明                                1
		  再做下一次处理时,将数组中最低有效位与计算出实际有效位不等的整数全部排除,用剩下的整数进行下一个有效位
		  的计算
输入:
6(0到n中的n,接下来给出n个元素)
00000 00001 00010 00100 00101 00110(n个元素)
输出:
3

关键:
1	通过分析最低有效位(若指定最低有效位为1,则表明每个整数的最后一位上的数字)中1和0的数字结果来确定。
    假设: 0000, 0001, 0010
	观察发现:如果n为奇数,则在最低有效位为1时,count(0)=count(1);n为偶数,count(0) = count(1) + 1
	规律: count(0) >= count(1)
	如果除去丢失的整数,统计的某最低有效位: count(0) <= count(1),则说明该丢失的整数的该最低有效位应该为0
		                                    count(0) > count(1),  则说明                                1
	再做下一次处理时,将数组中最低有效位与计算出实际有效位不等的整数全部排除,用剩下的整数进行下一个有效位
	的计算
2 bitset是一个bit对象,而不是一群bit对象
bitset<32> bitesetNum(value);//设定bit最长长度为32位,并用字符串初始化比特对象

3	//如果为空,直接返回0,必须返回0,否则递归的结果用于左移会有问题
	if( vecBitset.empty() )
	{
		return 0;
	}

	//说明丢失整数的第coulumn位为0,则只保留当前位为0的所有整数
	if(count0 <= count1)
	{
		int v = findLostNumber(vecZeros , column + 1 , columnMax);
		return (v << 1) | 0; // 插入当前结果最低有效位为0
	}
*/

//除了传入需要计算的biset集合外,还需要传入当前处理的是第几位的比特
int findLostNumber(vector< bitset<32> >& vecBitset , int column , int columnMax)
{
	//如果为空,直接返回0,必须返回0,否则递归的结果用于左移会有问题
	if( vecBitset.empty() )
	{
		return 0;
	}
	if(column >= columnMax)
	{
		return 0;
	}
	vector< bitset<32> >::iterator it;
	vector< bitset<32> > vecOnes;
	vector< bitset<32> > vecZeros;
	for(it = vecBitset.begin() ; it != vecBitset.end(); it++)
	{
		bitset<32> bitsetNum = *it;
		//统计当前第i位为0或1
		int value = bitsetNum[column];
		if(value == 1)
		{
			vecOnes.push_back(bitsetNum);
		}
		else
		{
			vecZeros.push_back(bitsetNum);
		}
	}
	int count0 = vecZeros.size();
	int count1 = vecOnes.size();
	//说明丢失整数的第coulumn位为0,则只保留当前位为0的所有整数
	if(count0 <= count1)
	{
		int v = findLostNumber(vecZeros , column + 1 , columnMax);
		return (v << 1) | 0; // 插入当前结果最低有效位为0
	}
	else
	{
		int v = findLostNumber(vecOnes , column + 1 , columnMax);
		return (v << 1) | 1;
	}
}

void process()
{
	int n;
	string value;
	vector< bitset<32> > vecBitset;
	while(cin >> n)
	{
		for(int i = 0 ; i < n ; i++)
		{
			cin >> value;
			bitset<32> bitesetNum(value);//设定bit最长长度为32位,并用字符串初始化比特对象
			vecBitset.push_back(bitesetNum);
		}
		//
		int result = findLostNumber(vecBitset , 0 , 32);
		cout << result << endl;
	}
}

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

程序员面试金典(java版)

1确定字符互异 2原串翻转 3原串翻转 4原串翻转 5基本字符串压缩1.1、确定字符互异 题目描述 请实现一个算法,确定一个字符串的所有字符是否全都不同。这里我们要求不允许使用额外的存储结构...
  • sinat_29912455
  • sinat_29912455
  • 2016年06月27日 23:51
  • 1309

《进军硅谷——程序员面试揭秘》

摘要:硅谷是绝大多数程序员梦想工作的地方,但你是不是真的做好进军硅谷的准备了?硅谷程序员面试有什么要求?本书作者从职位选择、公司选择、人际关系及求职渠道四个角度为广大IT从业人员揭密了硅谷程序员的求职...
  • alibo2008
  • alibo2008
  • 2014年04月17日 11:35
  • 2768

cracking the coding interview 中文版 (程序员面试金典)

 转自:CTCI面试系列——谷歌面试官经典作品 | 快课网 谷歌面试官经典作品(CTCI)目录 1.1 判断一个字符串中的字符是否唯一 1.2 字符串翻转 1.3 去除字符串中重复字符 ...
  • hnuzengchao
  • hnuzengchao
  • 2014年10月19日 11:32
  • 23460

程序员面试金典: 9.5位操作 5.6交换某整数的奇数位和偶数位

#include #include using namespace std; /* 问题:编写程序,交换某个整数的奇数位和偶数位,使用指令越少越好(也就是说,位0与位1交换,位2与位3交换,依...
  • qingyuanluofeng
  • qingyuanluofeng
  • 2017年01月03日 22:29
  • 136

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

#include #include #include #include using namespace std; /* 问题:给定一个介于0和1之间的实数(如0.72),类型为double...
  • qingyuanluofeng
  • qingyuanluofeng
  • 2017年01月03日 12:22
  • 175

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

#include #include #include #include #include using namespace std; /* 问题:有个单色屏幕存储在一个一维字节数组中,使得...
  • qingyuanluofeng
  • qingyuanluofeng
  • 2017年01月04日 13:18
  • 136

程序员面试金典: 9.7位操作 7.4只用加号实现整数的乘法、减法和除法运算

#include #include using namespace std; /* 问题:编写方法,实现整数的乘法、减法和除法运算。只允许使用加号。 分析:乘法比较简单,x*y等于将x连续累加...
  • qingyuanluofeng
  • qingyuanluofeng
  • 2017年01月05日 01:09
  • 218

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

#include #include #include using namespace std; /* 问题:给定一个整数数组(有正数有负数),找出总和最大的连续数列,并返回总和 分析:这个是...
  • qingyuanluofeng
  • qingyuanluofeng
  • 2017年01月16日 22:05
  • 256

程序员面试金典: 9.4树与图 4.3给定一个有序整数数组,元素各不相同且按升序排列,创建一颗高度最小的二叉查找树。

#include #include using namespace std; /* 问题:给定一个有序整数数组,元素各不相同且按升序排列,编写一个算法,创建一颗高度最小的二叉查找树。 分析:二...
  • qingyuanluofeng
  • qingyuanluofeng
  • 2016年12月27日 17:29
  • 257

程序员面试金典——整数转化__(位运算)

题目描述 编写一个函数,确定需要改变几个位,才能将整数A转变成整数B。 给定两个整数int A,int B。请返回需要改变的数位个数。 测试样例: 10,5 返回:4 ...
  • sinat_24048051
  • sinat_24048051
  • 2017年05月29日 11:09
  • 99
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:程序员面试金典: 9.5位操作 5.7寻找丢失的整数
举报原因:
原因补充:

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