给出访问的网页日志文件:
Userid PageID
A 1
A 2
A 3
B 2
B 3
C 1
B 4
A 4
查找最常见的网页ID访问顺序:
for A : 1-2-3, 2-3-4
for B : 2-3-4
所以,2-3-4是最常见的。
我的想法:
map1<key:user_id, list<pageID> >
。list.size() == 3
时,创建一个新的结构three_hits
来保存三个pageID。map2<struct three_hits, int counter>
。声明:
struct three_hits
{
int f_page;
int s_page;
int t_page;
};
map<string, list<int> > map_hit;
map<struct three_hits, int> map_t_hits;
扫描记录:
for each( record: r in log)
{
if(map_hit.count(r.userid) >0)
{
map_hit[r.uid].second.push_back(r.pageID);
if(map_hit[r.uid].second.size() ==3)
{
list<int> tmp=map_hit[r.uid].second;
t_hits(tmp[0],tmp[1],tmp[2]);
// O(n lg n)
if( map_t_hits.count(t_hits) >0)
map_t_hits[t_hits]++;
else
map_t_hits[t_hits]=1;
}
else
{
list<int> tmp(r.pageID);
map_hit[r.uid]=tmp;
}
}
// O(n)
迭代map_t_hits
一次,找到价值最高的密钥(t_hits
)。
地图的时间 O(n lg n)和空间 O(n)。
有更好的解决方案吗?
答案 0 :(得分:0)
您可以考虑使用sort-merge执行此操作。首先使用用户id的稳定排序将给定用户的所有序列放在一起,保持原始顺序。然后对所有3个网页序列进行排序,最后计算相等序列的运行。这也是O(n log n)。它可能需要花费更多的时间在实践中,但如果使用内部存储器运行可能需要更少的存储,并且可以在外部存储器中运行,如果您在任何时候都有太多的数据存储。它是否真的更好取决于你的特定情况的细节。