Algorithm Amazon访谈:时间戳排序:查找三页子集序列重复的最大次数

Algorithm Amazon访谈:时间戳排序:查找三页子集序列重复的最大次数,algorithm,amazon,Algorithm,Amazon,亚马逊采访的问题是: 给定一个包含(用户Id、URL、时间戳)的日志文件,用户可以从一个页面导航到另一个页面。查找重复次数最多的三页子集序列。记录按时间戳排序 这个问题是我从学校里发现的 海报: 给定包含(用户Id、URL、时间戳)的日志文件,用户可以从一个页面导航到另一个页面。查找重复次数最多的三个页面子集序列。记录按时间戳排序 (尽管如此,直到面试后期我才被告知文件是按时间戳排序的。我问的第一件事是日志是否已排序,面试官说没有。) 我想我已经付出了我的全部——我似乎已经在正确的轨道上使用了h

亚马逊采访的问题是:

给定一个包含(用户Id、URL、时间戳)的日志文件,用户可以从一个页面导航到另一个页面。查找重复次数最多的三页子集序列。记录按时间戳排序

这个问题是我从学校里发现的

海报:

给定包含(用户Id、URL、时间戳)的日志文件,用户可以从一个页面导航到另一个页面。查找重复次数最多的三个页面子集序列。记录按时间戳排序

(尽管如此,直到面试后期我才被告知文件是按时间戳排序的。我问的第一件事是日志是否已排序,面试官说没有。)

我想我已经付出了我的全部——我似乎已经在正确的轨道上使用了hashmap。我总是让面试官知道我在想什么,并给出可能的结果、时间复杂性等

我不知道如何处理这个问题。“查找重复次数最多的三页子集序列”是什么意思?如果问题没有说“记录是按时间戳排序的”(海报就是这样),那么这会对问题产生什么影响?

对于“三页子集序列”,我猜它们的意思是三页必须相邻,但它们的内部顺序并不重要。(
A B C
=
C A B

公共元组GetMostFrequentTriplet(
IEnumerable条目,
TimeSpan?maxSeparation=null)
{
//假设“条目”已按时间戳排序
//为每个用户存储最后两个URL
var lastTwoUrls=新字典();
//计算每个URL三元组的出现次数
var counters=newdictionary();
foreach(分录中的var分录)
{
二元组;
如果(!lastTwoUrls.TryGetValue(entry.UserId,out lastTwo))
{
//没有以前的URL
lastTwoUrls[entry.UserId]=Tuple.Create((string)null,entry.Url,entry.Timestamp);
}
//(与null=>false的比较)
else if(entry.Timestamp-lastwo.Item3>maxSeparation){
//将比maxSeparation更长的间隔视为两个不同的会话。
lastTwoUrls[entry.UserId]=Tuple.Create((string)null,entry.Url,entry.Timestamp);
}
其他的
{
//一个或两个以前的URL
if(lastTwo.Item1!=null)
{
//两个以前的URL;三个与此URL相同。
//对这三个URL进行排序,这样它们的内部顺序就不重要了
var Url=新列表{lastwo.Item1,lastwo.Item2,entry.Url};
Sort();
var key=Tuple.Create(URL[0],URL[1],URL[2]);
//增量计数
整数计数;
counters.TryGetValue(key,out count);//如果找不到,则设置为0
计数器[键]=计数+1;
}
//输入新值,放弃最旧的值。
lastTwoUrls[entry.UserId]=Tuple.Create(lastTwo.Item2,entry.Url,entry.Timestamp);
}
}
元组maxKey=null;
int maxCount=0;
//查找具有最大计数的密钥
foreach(计数器中的var对)
{
if(maxKey==null | | pair.Value>maxCount)
{
maxKey=pair.Key;
maxCount=pair.Value;
}
}
返回maxKey;
}
代码遍历日志条目并为每个用户分离流。对于任何用户的每三个连续URL,我们增加该三元组的计数。由于这三个页面的顺序并不重要,我们通过排序以一致的方式对它们重新排序。最后,我们返回计数最高的三元组

因为每个用户只需要最后三个URL,所以我们只存储前两个URL。结合当前的URL,这就形成了我们需要的三元组

对于n个URL、m个唯一URL、u个用户和s个单次访问用户,该方法将进行2次n-2次u+s(=O(n))字典查找,并最多存储C(m,3)+u(=O(m3+u))元组

编辑:
根据请求之间的持续时间推断会话。如果它们之间的差异大于
maxSeparation
,则新请求将被视为来自该用户的第一个请求。

简单思想:按用户id分组,然后按时间戳排序。找出3页中最重复的模式。感谢您的解释和代码!你的代码注释得很好,但是你能用文字解释一下你的算法的基本思想并讨论它的效率吗?这将使你的答案更有帮助。谢谢这不处理URL可能重复的常见情况。假设用户打开主页,然后转到产品页面。然后,他结束会议,并在另一天再次打开网站,从主页转到购物车页面。现在根据您的解决方案,最后两个元组将包含homepage和productpage。现在在第二天(当读取第二天条目时),triplet的元组将包含(Homepage、productpage、Homepage),这可能会导致谬误在上述场景中,我认为应该忽略这些条目。@Pawan,因为日志文件中没有会话ID,所以您必须依赖时间戳。请看我的编辑。谢谢,我想这行得通。如果没有maxSeparation的值,那么我们也可以通过检查当前页面值与lastTwoUrls元组中的值来实现相同的功能。比如说,如果最后两个URL是{Homepage,ProductPage},而最新的条目又是Homepage,那么我们可以用{Homepage}创建一个新的LastTwoURL条目