版权声明:本文为博主原创文章,转载请注明出处-- https://blog.csdn.net/qq_38790716/article/details/90379156
关心数据挖掘和搜索引擎的程序员都知道,我们需要很多的计算机来存储和处理海量数据。然而,计算机难免出现硬件故障而导致网络联系失败或死机。为了保证搜索引擎的服务质量,我们需要保证每份数据都有多个备份。
简单起见,我们假设一个机器仅存储一个标号为ID的记录(假设ID是小于10亿的整数),假设每份数据保存两个备份,这样就有两个机器存储了同样的数据。
- 1.在某个时间,如果得到一个数据文件ID的列表,是否能够快速找出这个表中仅出现一次的ID?
- 2.如果知道只有一台机器死机(也就是说只有一个备份丢失)呢?如果有两台机器死机呢(假设同一个数据的两个备份不会同时丢失)?
解法一
在一堆ID中找到一个ID,这个ID只出现一次,其它都出现2次。
思路:使用数组存储ID出现的次数,然后遍历该数组,找出只出现一次的ID;时间复杂度为 ,空间复杂度为
void find_1(vector<int> array) {
int n = array.size();
vector<int> ans(n, 0);
for (int i = 0; i < n; ++i) {
ans[array[i]]++;
}
for (int i = 0; i < n; ++i) {
if (ans[i] == 1)
cout << i << endl;
}
}
解法二
思路:使用哈希表存储ID出现的次数,每次遇见一个ID,就向哈希表中增加一个元素;如果这个ID出现的次数为2,那么就从哈希表中删除该元素;时间复杂度为 ,空间复杂度最好情况下为 ,最坏情况下为
void find_2(vector<int> array) {
map<int, int> mp;
int n = array.size();
for (int i = 0; i < n; ++i) {
mp[array[i]]++;
if (mp[array[i]] == 2) {
mp.erase(array[i]);
}
}
for (auto m : mp) {
cout << m.first << " ";
}
cout << endl;
}
解法三
思路:
- (1)当列表中仅有一个 出现了 次,那么我们可以考虑异或的性质, ^ , ^ = ;我们将所有的元素进行异或,得到的最终值即为只出现一次的 ID
- (2)当列表中有两个 出现了一次,那么我们用上面的方法显然行不通;我们可以将该问题转换为上一个问题,先将所有元素进行异或得到一个非零值 ,然后找到 的二进制表示中第一个非 的位,再根据该位判断列表中的元素,将元素分为两边,然后两边中的所有元素分别进行异或,最后得到两个非零值即为出现一次的两个
//列表中只有一个ID出现了1次
void find_3x(vector<int> array) {
int x = array[0];
for (int i = 1; i < array.size(); ++i) {
x ^= array[i];
}
cout << x << endl;
}
//列表中有两个ID出现了1次
int FindBit(int x);
bool IsBit(int x, int indexBit);
void find_3y(vector<int> array) {
int x = array[0];
for (int i = 1; i < array.size(); ++i) {
x ^= array[i];
}
int indexBit = FindBit(x);
int num1 = 0, num2 = 0;
for (int i = 0; i < array.size(); ++i) {
if (IsBit(array[i], indexBit))
num1 ^= array[i];
else
num2 ^= array[i];
}
cout << num1 << " " << num2 << endl;
}
int FindBit(int x) {
int indexBit = 0;
while ((x & 1) == 0 && indexBit < 8 * sizeof(int)) {
x = x >> 1;
++indexBit;
}
return indexBit;
}
bool IsBit(int x, int indexBit) {
x = x >> indexBit;
return (x & 1);
}
解法四
思路:求出原 序列的和 及乘积 ,当前 序列的和 及乘积 ; , ( 为故障机器 );遍历 ,满足这两个条件即为故障机器
void find_4(vector<int> array1, vector<int> array2) {
int sum1 = 0, sum2 = 0;
int mul1 = 1, mul2 = 1;
for (int i = 0; i < array1.size(); ++i) {
sum1 += array1[i];
mul1 *= array1[i];
}
for (int i = 0; i < array2.size(); ++i) {
sum2 += array2[i];
mul2 *= array2[i];
}
int a = sum1 - sum2;
int b = mul1 / mul2;
for (int i = 0; i < a; ++i) {
for (int j = 0; j < b; ++j) {
if ( i + j == a && i * j == b) {
cout << i << " " << j << endl;
return;
}
}
}
}
测试及代码:
#include <iostream>
#include <vector>
#include <map>
using namespace std;
void find_1(vector<int> array) {
int n = array.size();
vector<int> ans(n, 0);
for (int i = 0; i < n; ++i) {
ans[array[i]]++;
}
for (int i = 0; i < n; ++i) {
if (ans[i] == 1)
cout << i << endl;
}
}
void find_2(vector<int> array) {
map<int, int> mp;
int n = array.size();
for (int i = 0; i < n; ++i) {
mp[array[i]]++;
if (mp[array[i]] == 2) {
mp.erase(array[i]);
}
}
for (auto m : mp) {
cout << m.first << " ";
}
cout << endl;
}
//列表中只有一个ID出现了1次
void find_3x(vector<int> array) {
int x = array[0];
for (int i = 1; i < array.size(); ++i) {
x ^= array[i];
}
cout << x << endl;
}
//列表中有两个ID出现了1次
int FindBit(int x);
bool IsBit(int x, int indexBit);
void find_3y(vector<int> array) {
int x = array[0];
for (int i = 1; i < array.size(); ++i) {
x ^= array[i];
}
int indexBit = FindBit(x);
int num1 = 0, num2 = 0;
for (int i = 0; i < array.size(); ++i) {
if (IsBit(array[i], indexBit))
num1 ^= array[i];
else
num2 ^= array[i];
}
cout << num1 << " " << num2 << endl;
}
int FindBit(int x) {
int indexBit = 0;
while ((x & 1) == 0 && indexBit < 8 * sizeof(int)) {
x = x >> 1;
++indexBit;
}
return indexBit;
}
bool IsBit(int x, int indexBit) {
x = x >> indexBit;
return (x & 1);
}
void find_4(vector<int> array1, vector<int> array2) {
int sum1 = 0, sum2 = 0;
int mul1 = 1, mul2 = 1;
for (int i = 0; i < array1.size(); ++i) {
sum1 += array1[i];
mul1 *= array1[i];
}
for (int i = 0; i < array2.size(); ++i) {
sum2 += array2[i];
mul2 *= array2[i];
}
int a = sum1 - sum2;
int b = mul1 / mul2;
for (int i = 0; i < a; ++i) {
for (int j = 0; j < b; ++j) {
if ( i + j == a && i * j == b) {
cout << i << " " << j << endl;
return;
}
}
}
}
int main() {
vector<int> array = {1, 1, 2, 2, 4};
find_1(array);
find_2(array);
//test1
find_3x(array);
//test2
vector<int> array_y = {1, 1, 2, 2, 5, 4};
find_3y(array_y);
vector<int> array1 = {1, 1, 2, 2, 5, 5};
vector<int> array2 = {1, 1, 2, 5};
find_4(array1, array2);
return 0;
}
结果: