机器故障问题

 
 
机器故障
有很多的机器,每一个机器都有一个ID,每一个机器都有一个备份。如果某一天有一个机器死机了,你能找到她吗? 这个问题的意思也就是有一个ID的列表,其他的ID都出现2次,只有这个死机的ID出现一次。好比很多数中找出只出现一次的数。很简单吧。利用数组保存ID出现次数,遍历一次就找到了。时间复杂度O(n),空间复杂度也是O(n)。 可是如果ID数量多达几亿呢,你不是很拙计吗?哦,可是动态申请数组,如果出现不同的ID就给他删除。这样空间复杂度最坏同样是O(n)。再想一想,想起来水王哥。这和那个问题是一样的,只不过是求出现一次的ID。这样ID列表肯定是奇数啦。删除到最后得到的肯定是出现一次的ID,这个就不详述了,详见水王哥问题。 还有别的方法吗?可以比水王哥问题还简单吗?哦,位操作,前天刚学过。两个相同的ID异或得到0,如果全部的ID异或,那得到的就是仅仅出现一次的ID。时间复杂度是O(n),空间复杂度是O(1),nice算法哈。这个代码就很简单了,不写了。(ID=0,ID^=Id[i];) 可是,如果是两台机器死机了呢?你还能找到这两个ID吗?拙计吗?好好思考一下。这还是和位操作有些关系的。 我们想一想如果所有的ID异或,最后得到的ID=Id[a]^Id[b]。我们用什么办法求?这样ID列表肯定是偶数啦。这样异或后的ID的二进制中的1肯定只是这两个ID中的某一个中的1 。如果我们最后的ID按某一位上有1给他分成两类,这样分别异或,肯定也会分别得到最后的Id,很nice吧。 编码实现

#include<iostream>
using namespace std;
const int N=10; //必然是偶数
int main()
{
	int Id[N]={1,7,3,4,1,2,3,4,5,2};
	int Id1,Id2;      //两个死机的ID
	int ID=0;//ID=id1^id2
	Id1=Id2=0;
	for(int i=0;i<N;i++)
		ID^=Id[i];
	for(int j=0;j<sizeof(int)*8;j++)
	{
		if((ID>>j)&1==1) //第j位为1
			break;
	}
	for(i=0;i<N;i++)
	{
		if((Id[i]>>j)&1==1) //按第j位是否为1分类
			Id1^=Id[i];
		else
			Id2^=Id[i];
	}

	cout<<"Id1="<<Id1<<endl;
	cout<<"Id2="<<Id2<<endl;

	return 0;
}

	可是,假设ID有重复的,死机的那两个ID有肯定相同,这你还能这样做吗?哈哈,面试官这样一直逼问你,你跪不?NO,继续静心思考一下。
	然后想到了二元一次方程中的变量与不变量。不变量是什么,是全部ID(包括死机的ID)的值,是他的和,他的乘积,等等。如果事先有全部ID的和、乘积。我们再求现有ID的和、乘积,很明显我们能够得到一个二元一次方程。这样求解就很简单了。时间复杂度是O(n),空间复杂度是O(1)。
	可是求乘积的话,很多ID相乘可能会溢出啊。。我们可以用平方和,ID的平方求和。也同样得到结果。这个方法同样适用于ID不同的两个死机问题。编码实现就太简单了。
	如果我问你,如果每台机器3个备份,这时候有3台机器死机呢?上述那种方法还是可以用的?用方程法来求解完全没有问题啦。所谓万变不离其宗。

转载请注明出处http://blog.csdn.net/sustliangbo/article/details/9289429


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值