程序员面试金典: 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;
}

相关文章推荐

程序员面试金典: 检查是否为BST、 寻找下一个结点

1.检查是否为BST 题目描述 请实现一个函数,检查一棵二叉树是否为二叉查找树。给定树的根结点指针TreeNode* root,请返回一个bool,代表该树是否为二叉查找树。...

《程序员面试金典》--寻找二叉树中两个节点的第一个公共祖先(三种情况)

/***************************************************************************************************...
  • zdplife
  • zdplife
  • 2015年10月26日 19:21
  • 1585

程序员面试金典--面试22之寻找二叉树中指定结点的下一个结点

题目描述 请设计一个算法,寻找二叉树中指定结点的下一个结点(即中序遍历的后继)。 给定树的根结点指针TreeNode* root和结点的值int p,请返回值为p的结点的后继结点的值。...

程序员面试金典2.1:编写代码,移除未排序的链表中的重复节点

2.1编写代码,移除未排序的链表中的重复节点 解法一:如果不得使用临时缓冲区,该怎么解决? 要想移除链表中的重复节点,我们需要设法记录有哪些是重复的。这里只需要使用到一个简单的散列表。 在下面的解法中...

《程序员面试金典》链式A+B

【 声明:版权所有,转载请标明出处,请勿用于商业用途。  联系信箱:libin493073668@sina.com】 题目链接:http://www.nowcoder.com/p...

【程序员面试金典】确定两串乱序同构

一.题目描述 给定两个字符串,请编写程序,确定其中一个字符串的字符重新排列后,能否变成另一个字符串。这里规定大小写为不同字符,且考虑字符串重点空格。给定一个string stringA和一个stri...

[程序员面试金典]1001.字符串变换

题目描述现有一个字典,同时给定字典中的两个字符串s和t,给定一个变换,每次可以改变字符串中的任意一个字符,请设计一个算法,计算由s变换到t所需的最少步数,同时需要满足在变换过程中的每个串都是字典中的串...

【程序员面试金典】集合栈

【程序员面试金典】集合栈

程序员面试金典第二章:链表(6) 链表环路

1.1 问题描述 给定一个链表,判断该链表是否有环路,如果有,就返回链表环路开始的结点,如果没有,返回nullptr 1.2 解题思路 思路1:判断链表是否有环路,通常采用快慢指针法,所谓...

《程序员面试金典》--像素反转

题目描述:    有一副由NxN矩阵表示的图像,这里每个像素用一个int表示,请编写一个算法,在不占用额外内存空间的情况下(即不使用缓存矩阵),将图像顺时针旋转90度。    给定一个NxN的矩阵...
  • zdplife
  • zdplife
  • 2015年09月11日 19:20
  • 344
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:程序员面试金典: 9.5位操作 5.7寻找丢失的整数
举报原因:
原因补充:

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