快速找出机器故障

快速找出机器故障

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

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

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

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

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

          异或性质如下:

输入
运算符
输入
结果
1
0
1
1
1
0
0
0
0
0
1
1

解法一

  直接遍历列表,利用一个数组记录下每个ID出现的次数,遍历完毕之后,出现次数小于2的ID就是我们想要的结果。

  假设有N个ID,且ID的取值在0~N-1之间,这个解法占用的时间复杂度为O(N),空间复杂度为O(N)。

  时间复杂度已经相当理想,但是空间复杂度不够理想,如果ID的数量多达几个G甚至几十G,这样的空间复杂度在实际的运算中就会带来效率问题。

解法二

  考虑到大部分ID的出现次数都等于2,这些ID的信息并不是必要的,所以不必存储。

  因此,可以把解法一数组中等于2的元素清空,然后用来存储下一个机器ID的出现次数,这样就可以减少需要的空间。

  具体方法如下:遍历列表,利用哈希表记下每个ID出现的次数,每次遇见一个新的ID,就向哈希表中增加一个元素;如果这个ID出现的次数为2,那么就从哈希表中删除这个元素,最后剩下的ID就是我们想要的结果。

  这个算法的空间复杂度在最好情况下可以达到O(1),在最坏的情况下仍然是O(N)。

解法三

  对于第一问,假设列表中仅有一个ID出现了一次,那么可以考虑用异或关系来帮忙找到结果。

  因为异或运算的定义是相同为假相异为真,异或运算满足交换律和结合律。

  所以,所有ID的异或值就等于这个仅出现一次的ID。(两两相同的都得到0,0和任何值异或等于原来的任何值)

  这种情况下,时间复杂度为O(N),空间复杂度为O(1)。

 

  对于第二问,由于有两个ID仅出现了一次,设它们为A和B,那么所有ID异或的结果是A异或B,但还是无法确定A和B的值。

  可以进行分类讨论:

  (1)A == B

  这时A异或B等于零,丢失的是同一份数据的两个拷贝,可以通过求和的方法求得A和B,即,所有ID值的和减去所有正常的ID之和,除以2得到A和B。

  (2)A !=B

      1.对数组中所有的ID进行异或,结果为a
      2.我们找到a的二进制表示中,最低一位为1的位置b(无论是最低位1,还是最高位1,只要某个位为1,则可以利用这个位,将数组分成分别包含A和B的数组)
      3.根据b位是否为1,将ID数组中的数分为两个数组,其中一个数组中的b位为1,另一个队列中的b位为0。
       (注意,每个数组中,除了那个只出现一次的数外,其他数都是出现两次的,此时就可以在数组内使用异或操作,将这个问题变成了             两个数组,每个数组都缺一个数,此时就转换成了第一问的问题了)
      4.然后对两个数组,分别进行异或操作,则将得到两个不为0的数字。即为所丢失的两个ID。

   我们分别计算这两类的异或和,即可得到A和B的值。(对于这种情况是最好的解)

解法四

  对于第一问,缺失一个ID:

  预先计算并保存好所有ID的求和(“不变量”),顺序列举当前所有剩下的ID,对它们求和,然后用所有ID的求和减去当前剩下所有ID的和,结果就是死机的机器的ID值。

  时间复杂度为O(N),空间复杂度为O(1),和解法三一样是计算复杂度最优的算法。

 

  对于第二问,我们考虑所有的情况,即两个ID可以相同也可以不同(通用解法)。

  用上面的方法可以得到这两个ID的和。我们构造出一个方程: x + y = a; a已知。

  第二个方程有很多构造方法,比如可以用所有ID的乘积计算出另一个不变量,除以所有剩下的ID,结果得到两台死机机器的ID的乘积,即x * y = b。

  这样联立两个方程之后,可以解出x和y的值。

  时间复杂度为O(N),空间复杂度为O(1)。

  第二个方程构造也可以考虑平方和的方法。

举个例子如下:

例1:7 7 6 6 3 5 (答案是3 5)

解: 设两数是A,B

所有数异或的结果C=A^B

如例子所有数异或后的结果为110

对于110这个二进制数来说,其中的1代表A和B有且仅有一个数在该位上为1

比如我取右起第一个二进制位(最右边第一个1),该位为1

对于所有数

111

111

110

110

011

101

按照第一位是否为1分成两组,A和B必定被分到两个不同的组里

111

111

110

110

101

011

第一组所有数异或后的结果为101,第二组为011,即A,B为101和011


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值