编程之美:第一章 1.5快速找出机器故障

/*
快速找出机器故障:
为了保证搜索引擎的服务质量,我们需要保证每份数据都有多个备份
假设一个机器仅存储了一个标号为ID的记录(假设ID是小于10亿的整数),假设每份数据保存了两个备份,这样
就有两个机器储存了同样的数据。
1在某个时间,如果得到一个数据文件ID的列表,是否能够快速地找出这个表中仅出现一次的ID?
2如果已经知道只有一台机器死机(也就是说只有一个备份都是)呢?如果有两台机器死机呢(假设同一个数据
的两个备份不会同时丢失)?
3如果丢失的两台机器ID相同呢?

分析:
这个问题可以转化成:有很多的ID,其中只有一个ID出现的次数小于2,其他正常ID出现的次数都等于2,如何找到
这个次数为1的ID。
这样就转化成剑指上面的:所有元素全部异或,最终剩下的数就是那个数

第二问转化为这群数中有两个数各出现一次,其余出现0次,所以也是剑指上的题目,需要全部异或得到数字
x,然后获取x的比特表示中最右边的1,记为该位为第n位,根据比特表示中的第n位是否为1,将数组划分
成两部分,每一部分中在分别全部异或一遍,即可。
局限:只能解决两台故障机器ID不同的情况。如果ID相同,则无法解决

第三问:
预先计算并保存好所有ID的求和(不变量),顺序列举当前所有剩下的ID,对它们求和,然后用总值 - 剩余值 = 死机
的机器ID值。由于总和可以先计算好,算法的时间复杂度为O(N),空间复杂度为O(1)

当两个ID不同时:总和 - 剩余和 = x + y
当两个ID相同时:这个时候,x = (总和-剩余和)/2

这个时候可以构造二元一次方程组来做,比如:总乘积/剩余乘积 = x*y(或者求出x*x + y*y = b)
联立解方程
{x + y = a
{x * y = b
此方法的缺陷是:需要事先知道原来n个数,如果题目只给你丢失的数,那就坑爹了

样例输入:
8
2 4 3 6 3 2 5 5
2 4 3 6 3 2 5 5 4 6
样例输出:
4 6
*/

#include <stdio.h>
#include <math.h>
const int MAXSIZE = 10000;

void process()
{
 int n;
 while(EOF != scanf("%d",&n))
 {
  if(n < 0)
  {
   break;
  }
  int iRemainArr[MAXSIZE];
  long long lRemainSum = 0,lRemainMul = 1,lIntactSum = 0,lIntactMul = 1;
  for(int i = 0 ; i < n ; i++)
  {
   scanf("%d",&iRemainArr[i]);
   lRemainSum += iRemainArr[i];
   lRemainMul *= iRemainArr[i];
  }
  int iIntactArr[MAXSIZE];
  for(int j = 0 ; j < n + 2 ; j++)
  {
   scanf("%d",&iIntactArr[j]);
   lIntactSum += iIntactArr[j];
   lIntactMul *= iIntactArr[j];
  }
  long long lSum = lIntactSum - lRemainSum;
  long long lMul = lIntactMul/lRemainMul;
  long long lSqrt = (long long)sqrt(double(lSum*lSum - 4*lMul) + 0.5);
  long long lX = (long long)((lSum - lSqrt)/2);
  long long lY = (long long)((lSum + lSqrt)/2);
  printf("%lld %lld\n",lX,lY);
 }
}

int main(int argc,char* argv[])
{
 process();
 getchar();
 return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值