#include <iostream>
#include <stdio.h>
#include <map>
#include <vector>
using namespace std;
/*
问题:你会如何设计诸如Facebook或Linkedln的超大型社交网站?请设计一种算法,展示两个人之间的"连接关系"或"社交路径"
(比如:,我->鲍勃->苏珊->杰森->你)
分析:实际是一种搜索。最简单的办法就是暴力破解。遍历我的每一个朋友,然后对于我的每一个朋友继续遍历。
这样的话,时间复杂度为O(2^n),必须要剪枝,关键是如何剪枝呢?
深度优先搜索或广度优先搜索。 广度优先搜索用于计算最优问题,深度优先搜索用于计算是否有解问题。
如果考虑每个人的朋友较少,即总人数较少的情况下,是可以用广度优先搜索实现。
书上解法:
步骤1:如何在大数据的情况下,找到自己的朋友。
人数非常多的时候,每个人的信息一般按照人的id分配在不同的机器上,比如按某种哈希散列后,存储在不同地方。
最关键就是<人的id,机器id>,<机器id,人的id>,根据人的id想要获取人的信息,需要做以下处理:
根据人的id找到机器id,根据机器id找到机器,获取机器上保存的<人的id,人>映射,获取人的信息。
这是服务器类。
步骤2:采用广度优先搜索,不用深度优先搜索的原因是两个人可能直接是朋友,如果深度优先搜索,可能搜索几百万结点
后发现不是,再继续搜,效果太差了
关键:
1
步骤1:如何在大数据的情况下,找到自己的朋友。
人数非常多的时候,每个人的信息一般按照人的id分配在不同的机器上,比如按某种哈希散列后,存储在不同地方。
最关键就是<人的id,机器id>,<机器id,人的id>,根据人的id想要获取人的信息,需要做以下处理:
根据人的id找到机器id,根据机器id找到机器,获取机器上保存的<人的id,人>映射,获取人的信息。
这是服务器类。
步骤2:采用广度优先搜索,不用深度优先搜索的原因是两个人可能直接是朋友,如果深度优先搜索,可能搜索几百万结点
后发现不是,再继续搜,效果太差了
2
人类: 每个人包含自己的id,以及朋友id列表,而不是朋友列表,因为存储朋友列表会浪费空间
机器类:存储了<人的id,人>的映射,包含自身机器id
服务类:服务器类,存储<人的id,机器id>,<机器id,人的id>的映射
服务类提供的最主要功能是根据用户id获取用户信息
3 扩展问题:
1)划分用户和机器,尽量按国家,城市,进行划分,减少跳转
2)找到同一机器上的多个朋友后,再跳转
3)广度优先搜索标记访问结点不要直接编辑数据,可以用散列表<id,该id是否访问过>
4)优先选择自己朋友中拥有朋友个数较多的人作为起点遍历
5)搜索到何时放弃,即存在剪枝,比如最多深度为100时就不再搜索
*/
//人,每个人包含自己的id,以及朋友id列表,而不是朋友列表,因为存储朋友列表会浪费空间
class Person
{
public:
Person(int id):_id(id){}
void addFriend(int id)
{
friends.push_back(id);
}
int _id;
vector<int> friends;
};
//机器,存储了<人的id,人>的映射,包含自身机器id
class Machine
{
public:
Machine():_isNull(false){}
//可以根据人的id获取人
Person getPerson(int personId)
{
map<int , Person>::iterator it = personIdToPerson.find(personId);
if(it != personIdToPerson.end())
{
return it->second;
}
else
{
return NULL;
}
}
private:
map<int , Person> personIdToPerson;
//机器包含机器id
int _machineId;
public:
bool _isNull;
};
//服务器类,存储<人的id,机器id>,<机器id,人的id>的映射
class Server
{
public:
Server(){}
void init(){}
int getMachineId(int personId)
{
map<int , int>::iterator it = personIdToMachineId.find(personId);
if(it != personIdToMachineId.end())
{
return it->second;
}
else
{
return -1;
}
}
Machine getMachine(int machineId)
{
map<int, Machine>::iterator it = machineIdToMachine.find(machineId);
if(it != machineIdToMachine.end() )
{
return it->second;
}
else
{
Machine machine;
machine._isNull = true;
return machine;
}
}
//服务类提供的最主要功能是根据用户id获取用户信息
Person getPersonByPersonId(int personId)
{
int machineId = getMachineId(personId);
if(-1 == machineId)
{
return NULL;
}
Machine machine = getMachine(machineId);
Person person = machine.getPerson(personId);
return person;
}
private:
map<int , int> personIdToMachineId;
map<int, Machine> machineIdToMachine;
};
int main(int argc , char* argv[])
{
getchar();
return 0;
}
程序员面试金典: 9.10 扩展性与存储限制 10.2寻找社交网站中的朋友路径
最新推荐文章于 2017-01-11 22:01:40 发布