zoukankan      html  css  js  c++  java
  • 编程之美 1.5快速找出故障机器

    题目:

      有很多服务器存储数据,假设一个机器仅存储一个标号为ID的记录,假设机器总量在10亿以下且ID是小于10亿的整数,假设每份数据保存两个备份,这样就有两个机器存储了同样的数据。

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

        2.如果有两台机器出现故障呢?(假设存储同一份数据的两台机器不会同时出现故障,即列表中缺少的是两个不等的ID)

    给出了4种解法思路

    解法一:

      最传统的比较列表,需要遍历整个列表,记录每个ID出现的次数,最后输出只出现一次的ID,时间复杂度O(n),空间复杂度也为O(n),如果数据量太大,实际运算效率会很低下。

    解法二:

      优化存储空间,在很多数据中,大部分出现次数都是2,出现故障的机器为少数,通过Hash Table,Key值为机器ID,Value值为出现次数。遍历列表,遇到ID,就将ID的Value值加1。Value值为2的话,删除这个Key。最后Hash表中剩下的就是出故障的机器ID。

      最好情况下空间复杂度为O(1),最坏仍为O(n)。

    解法三:

      前两种方法已经将空间复杂度降到了O(n),如果在想降到常数级,就需要换一种思路,不用遍历列表的这种方法。

    如果能只用一个变量记录遍历列表的结果,那么空间复杂度可将为O(1)。

      x(N)=ID_Lost。考虑到列表中,只有一个ID出现了1次,其他都是2次,可以用到计算机语言里面的异或(XOR、⊕)。

    A⊕A=0

    A⊕0=A

      最终x(n)=List[0]⊕List[1]⊕List[2]⊕……⊕List[n]  的运算结果即为只出现一次的ID号,空间复杂度为1。

      但如果有2个ID只出现了一次,假设出现一次的ID为A,B,x(n)的为A⊕B,仍无法确定AB的值。

      异或之后的二进制值,某一位为1的话,可以推断出,AB2个数中,这个位置,一个是0,一个是1。我们将所有ID,分为2类,一类这位上为1,一类这位上为0。这2类个包含了AB中的一个,使用2个变量,遍历列表做异或处理,即可找出A和B的值。

    解法四:

      将问题进行扩展,现在故障机器的ID相同,既2台存储相同数据的机器同时嗝屁了。运用一些数学上的知识,数学中有不变量,在这里,事先预订的整数ID集合中,所有的ID相加可以得到一个不变量将现在的ID集合相加,用不变量减去现在的ID集合的和,即可得到丢失数据ID的。时间复杂度为O(n),空间复杂度O(1)。

      如果这2台机器ID不同,我们只是得到了他们的ID之和,x+y=a,并不能知道他们到底是多少。可以再构建一个等式,构成一个方程,解方程组,得出x和y的值。同样使用不变量的概念,比如所有ID的乘积,最后得出来xy=b,解出x,y的值。

    总结:

      在算法设计是一个慢慢发展过程中,开始的时候可能只是想出了最普通的一个解法,效率不高,但能解决问题。做到这一步之后,想要更进一步,就需要在时间复杂度或者空间复杂度方面做一些优化。还可以根据题中的一些条件,想一些可以用计算机方式解决的方法,如异或、与、正则表达。还可以用数学的思想来看看问题有没有解决的办法。

    附解法一小程序

    #include "stdio.h"
    
    int main(){
        int List[]={1,2,3,5,6,7,8,9,0,1,2,3,4,5,6,8,9};//ȱ0,7,4 
        int t;
        int length=sizeof(List)/sizeof(List[0]);
        printf("%d
    ",length);
    
        for(int i=0;i<length;i++){
        t=0;
            for(int j=0;j<length;j++)
                if(List[i]==List[j])
                    t=t+1;
        if(t!=2)
            printf("%d
    ",List[i]);
        }
    } 
  • 相关阅读:
    魅族--魅蓝metal
    小米2015.11.24 雷军:我所有的向往
    微软2015.10.4发布会
    创意app1
    奇怪的想法2
    奇怪想法1
    对不起,我爱你(悲剧,慎入)
    聊聊台式机1
    聊聊笔记本1--人生第一台笔记本
    聊聊路由器1
  • 原文地址:https://www.cnblogs.com/SeekHit/p/5111080.html
Copyright © 2011-2022 走看看