快速找出故障机器

题目:假设一个机器只存储一个标号为ID的记录,假设每份数据保存2个备份,这样就有2个机器存储了相同的数据。其中ID是小于10亿的整数

问题1、在某个时间,如果得到一个数据文件ID的列表。是否能够快速的找到这个表中仅出现一次的ID?即快速找出出现故障的机器存储的数据ID。

问题2、如果有两台机器死机呢?(假设同一个数据的俩个备份不会同时丢失,即列表中缺少的是两个不等的ID)

扩展题、如果所有的机子都有三个备份,也就是说同一ID的机子有三台。而且同时又有三台机子死机,还能用上面的方法解决吗?

如果有N台备份,又同时有N台机器死机呢?



本来以为自己能够想到一个很好的另外的方法,后来想了半天还是没想到,就只看看书上的解法把!

解法一:

最原始的方法,直接扫描整个列表,把每个ID出现的次数给记录下来,那么最后我们得出,出现一次的就是那个故障机器的ID。

注意我们直接建立一个长度为N的数组,每个元素初始化为0,扫描列表的时候,直接根据ID作为下标去把数组中的元素+1.

解法二:

思考一下解法一其实就是解法一的变更,就多了一个哈希表,我们在解法一中,直接使用了一个长度为N的数组,其实我们可以使用一个哈希表,我们使用的是动态存储的方式,没扫描到一个ID,使用散列函数哈希出一个值,然后根据这个值去寻找其存储的ID是不是已经有了,已经有了,就直接把存储这个ID的元素删除了,没有的话就存储下来。

这样最好的情况就是只使用了一个存储单元,最好的情况是什么呢?就是列表张这个样子:1,1,2,2,3,3,4,4,5,5..........

但是最坏的的情况是使用了N个单元:1,2,3,4,5..........N,1,2,3,4,5.......N.

解法三:

此解法是一个很精妙的算法,很佩服想到这个算法的人。

它用到了亦或运算:⊕,我们知道亦或运算满足这样的性质:X⊕X=0,X⊕0=X。

对于我们这个运算真是太实用了。

为什么呢?

我们假设这样的坏掉的两个机器的ID分别是X和Y。

正常如果没坏的机器的话,我们把列表的所有的ID进行求亦或运算结果一定是0,原因是ID都是成双成对的。

那么在坏掉之后我们再把列表的ID进行亦或,如果亦或的结果是0,这代表什么呢?

这当然代表列表中的ID也是成双成对的啊,那么坏掉的那两台机器的ID就是一样的喽。接下来我们把原来的所有的ID的和再减去现在的ID列表的ID的和,不就是X+Y了吗?而我们又知道X=Y,不就可以求出X了吗?

如果是亦或的结果不等于0,那其实亦或的结果就是X⊕Y的结果,原因自己想。那么这个结果肯定就是其二进制中数的某一位为1,显然就是X和Y中有且仅有一个数的相同位上也为1。那么我们就把列表中的ID分为两类,一类是这个位上的数是1的,一类是这个位上的数是0的,然后我们分别计算着两类ID的亦或值,这样分别计算出来了X和Y。

解法四:

仔细瞅瞅解法三中的亦或值等于0的情况,其实它就是对于两个变量X和Y,找到了两个方程,解方程而已。

根据此解法,我们可以这样想,对啊,我直接根据X,Y两个变量,再去找他们的相关的两个方程不就得了。

怎么找呢?解法三中的把原来的ID和减去之后的ID和得出X+Y的值,这已经算是一个方程,根据这个方程,我们其实可以再去构造一个方程,什么呢?平方和嘛。我们把原来的列表的每个ID的平方和求出来,再把现在的列表的ID的平方和求出来,减一下,不是就得出X的平方+Y的平方了吗?这不就又一个方程了吗?两个方程,两个未知数。

自己的想法:

对于书上的扩展问题,我们很容易的会想到解法四,既然我们用了平方构造出来了第二个方程,为什么不能用三次方构造出第三个方程,用四次方构造出第四个方程。

对于这个算法,我是这样想的,虽然三次方之后,要求的解很难算,但是电脑是可以解出来的。

        比如X= 3,Y= 4,Z= 5;

给你一个方程组,让你求三个未知数

X+Y+Z=12;

X^2 + Y^2 +Z^2 = 50;

X^3 + Y^3 + Z^3 =216

这个很多数学软件是都可以求解出来的。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值