确定,
我在一次采访中得到了这个问题,我认为我需要一些帮助来解决它。
你有一吨URL称为字符串数组或从文件中读取。您现在需要获得前十个最常读的,如文件中十大最常用的URL。
我的方法是:
Read them into a String Array,
Iterate through each String/URL,
At every Iteration, put them into Hashtable, incrementing the count.
Iterate again and find feed the scores into an array
Sort and find the top 10 scores OR use max-heap to get the top 10.
Iterate again and remove the URL's with the top 10 scores.
这是一个非常糟糕的答案吗?有人可以帮助我进一步解决这个问题吗?
答案 0 :(得分:2)
您可以使用最少的内存和基本上无限大小的文件来执行此操作:
Use the OS-supplied sort utility to sort the URLs on disk
Create a priority queue (binary heap, for example)
For each URL in the file
if the URL is the same as the previous URL
increase count
else
AddToQueue(previous_url, count)
previous_url = current_url
count = 1
EndFor
AddToQueue(previous_url, count)
此时,前10个访问量最多的URL将位于优先级队列中。
AddToQueue
函数如下所示:
AddToQueue(url, count)
if (queue.Count < 10)
add new url with count to queue
else if (count > top_of_queue.count)
remove top URL from queue
add new url with count to queue
如果您有足够的内存来加载所有URL,您可以将它们加载到一个数组中并对其进行排序。但是如果你有足够的内存用于所有的URL,那么基于字典的方法可能会更快。
答案 1 :(得分:0)
运行时并不坏,总体来说就像O(nlogn)。
Read them into a String Array - O(n)
Iterate through each String/URL - O(n)
At every Iteration, put them into Hashtable, incrementing the count - O(1)
Iterate again and find feed the scores into an array - O(n)
Sort and find the top 10 scores OR use max-heap to get the top 10 - O(nlogn)
Iterate again and remove the URL's with the top 10 scores. - O(1)
但是,你可以跳过最后两步。相反,遍历哈希表(或URL)的条目,并且当您浏览条目时,维护一个包含前10个分数的10个条目的数组;这样你跳过排序步骤,整个运行时将是O(n)。
答案 2 :(得分:0)
首先,请注意您不必要地使用额外的内存。为什么要将所有内容读入数组,然后遍历该数组以将所有内容插入哈希表中?除非你有充分的理由这样做,否则你应该在阅读时将它放入哈希表中。
这减少了对阵列的需求,并且通过O(n)减少了内存使用量。其他步骤听起来很合理。维护一个包含前10个分数的10个条目的数组的想法是一个很好的方法,但它提出了如何有效地做到这一点的问题。
此外,使用哈希表可能会引发实现问题,您过分依赖内置库中的内容。为了采访,可能更好的方法是将所有内容读入二叉搜索树,其中每个节点都包含一个带有字符串的结构,以及该字符串的出现次数(以及指向左右节点的指针)。通过二进制搜索树,您可以查看O(log(n))时间内是否存在字符串。阅读完所有内容并将其放入树中后,您可以使用shell排序对树进行排序。壳牌分类是这项运动的一个很好的选择,因为它可以迅速消除大量的疾病。此解决方案在O(nlog(n))时间内运行。
如果你的面试官可以使用哈希表,也许它不值得实现一棵树的麻烦,但是说“我会使用哈希表”你可以用脚射击自己,除非你当然实现哈希表。这实际上取决于具体情况。