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

#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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值