我在阅读这个问题之一时被要求接受软件工程师的面试。
如果有1000个网站和1000个用户,请编写一个程序和数据结构,以便我可以实时查询以下内容:1。给定任何用户,我获得他/她访问过的所有网站的列表2给定任何网站,我都会获得访问过它的所有用户的列表。
我认为他们想要一种伪代码或设计算法。
你们可以给出任何提示吗?
答案 0 :(得分:3)
有一件事是肯定的 - 为了能够回答两个查询,您需要存储所有意味着用户访问过给定网站的对。所以我建议如下:
你有一个结构:
struct VisitPair{
int websiteId;
int userId;
VisitPair* nextForUser;
VisitPair* nextForWebsite;
};
nextForUser将指向给定用户的下一对,如果给定用户没有下一对,则为NULL,类似于nextForWebsite将指向webSite的下一对。用户和网站看起来像:
struct User {
char* name;
VisitPair* firstPair;
};
struct Website {
char* url;
VisitPair* firstPair;
};
我假设网站和用户都存储在数组中,比如这些数组是websites
和users
。现在添加一个新的visitPair相对容易:
void addNewPair(int siteId, int userId) {
VisitPair* newPair = (VisitPair*)malloc(sizeof(VizitPair));
newPair->nextForUser = users[userId]->firstPair;
users[userid]->firstPair = newPair;
newPair->nextForWesite = websites[siteId]->firstPair;
websites[siteId]->firstPair = newPair;
}
打印网站的所有用户以及用户的所有网站都是通过简单地遍历列表来完成的,这样您就可以做到这一点。
简而言之,我创建的是一个集成了两个列表的结构。我不认为可以有一个更复杂的解决方案,因为这个解决方案在答案方面具有线性复杂性,并且在添加一对时具有恒定的复杂性。
希望这有帮助。
答案 1 :(得分:3)
对于每个网站和用户,分别为访问者和访问过的网站保留一个链接列表。每当用户访问网站时,在用户链接列表和网站链接列表中添加一个条目。
这具有最小的内存开销和快速更新和查询。
答案 2 :(得分:3)
由于网站数量和用户数量都是预先限制和已知的,因此您可以使用1000 x 1000维度的2D数组,其中用户为一维,网站为另一维。 该数组将是一个布尔数组。
bool tracker[1000][1000] ;
当用户x访问网站y时,它被标记为1(真)。
tracker[x][y] = 1;
要返回访问过网站J的所有用户, 返回列J中的所有值,其值为1,
返回用户i访问过的所有网站,返回第i行中值为1的所有值。
查找的复杂性是O(n),但这种方法是节省空间的,更新是0(1), 与链接列表不同,链接列表需要O(n)复杂性才能将用户添加到网站链接列表,或者将网站添加到用户的链接列表。(但这样做在查找时会产生O(1)复杂性。)
答案 3 :(得分:1)
一般情况下, N 用户和 M 网站都有两个地图用于查询,例如
map<user, set<site> > sitesOfUser;
map<size, set<user> > usersOfSite;
当用户你访问网站 s 时,请使用
进行更新sitesOfUser[ u ].insert( s );
usersOfSite[ s ].insert( y );
此处使用 set 来避免重复。如果复制正常(或者您稍后会处理),您可以只使用列表并通过其他日志缩短更新时间。
在这种情况下,更新将采用 O(logN + logM)时间(或仅 O(logN),见上文)并且查询将采用 O(logN)< / strong>时间。
在您的特定情况下,当网站和用户的最大数量不是太多并且事先已知时(假设它是 K ),您可以只有两个数组,如
set<site> sitesOfUser[ K ];
set<user> usersOfSite[ K ];
此处您将获得 O(logN)更新时间(或 O(1),如果重复信息不是问题而您使用列表或其他线性容器), O(1)查询时间。
答案 4 :(得分:1)
以下是已发布答案的摘要。
设m是站点数,n是用户数。 对于每个数据结构,我们给出了更新的复杂性,分别为。得到。
izomorphius的答案非常接近链表。
O(len(answer))是读取整个答案所需的时间,但是对于集合和列表,可以得到0(1)中的迭代器,它具有next
方法,该方法也得到保证O(1)。