问题如下
注意:假设您无法使用数据库。
实现结果的最佳数据结构是什么?
我之前考虑过使用地图,但地图并没有跟踪前10次点击的排序。
答案 0 :(得分:1)
你需要一个额外的List<Map.Entry<URL,Integer>>
来保持前十名,其中T是最下面的点击次数。
答案 1 :(得分:1)
我能想到的最好的数据结构是使用TreeSet。
TreeSet的元素已排序,因此您可以轻松找到热门项目。 还要确保URL保持一个单独的比较器类来实现 比较器,所以你可以把你的逻辑保持元素排序 基于计数的时间。在创建TreeSet时使用此比较器。插入/更新/删除/获取所有操作都在O(logn)
中进行
以下是代码,您应该如何定义结构。
TreeSet<URL> treeSet = new TreeSet<URL>(new URLComparator());
class URL {
private String url;
int count;
public URL(String string, int i) {
url = string;
count = i;
}
@Override
public int hashCode() {
return url.hashCode();
}
@Override // No need to write this method. Just used it for testing
public String toString() {
return "url : " + url + " ,count : " + count+"\n";
}
}
还有一个信息 - 使用您的URL类的哈希码方法作为您网址的哈希码。
这是您定义URLComparator类的方法。比较逻辑基于URL计数。
class URLComparator implements Comparator<URL> {
@Override
public int compare(URL o1, URL o2) {
return new Integer(o2.count).compareTo(o1.count);
}
}
<强>测试强>
TreeSet<URL> treeSet = new TreeSet<URL>(new URLComparator());
treeSet.add(new URL("url1", 12));
treeSet.add(new URL("url2", 0));
treeSet.add(new URL("url3", 5));
System.out.println(treeSet);
输出: -
[url : url1 ,count : 12
, url : url3 ,count : 5
, url : url2 ,count : 0
]
要打印前10个元素,请使用以下代码。
Iterator<URL> iterator = treeSet.iterator();
int count = 0;
while(count < 10 && iterator.hasNext() ){
System.out.println(iterator.next());
count++;
}
答案 2 :(得分:0)
您可以将Map<String, Integer>
用作用例:
跟踪key
(网址)和value
(点击次数)
当用户点击该网址时,您可put
向地图添加带有映射点击次数的更新网址。
根据entryset
// create a list out of the entryset of your map
Set<Map.Entry<String, Integer>> set = map.entrySet();
List<Map.Entry<String, Integer>> list = new ArrayList<>(set);
// this can be clubbed in another stub to act on top 'N' click counts
list.sort((o1, o2) -> (o2.getValue()).compareTo(o1.getValue()));
list.stream().limit(10).forEach(entry ->
System.out.println(entry.getKey() + " ==== " + entry.getValue()));
答案 3 :(得分:0)
使用Map,您必须对前10个网址的值进行排序。 这会使用比较器按值进行排序,从而使你(ologn)的复杂性降低。
另一种方式是:
将双向链表(大小为10)与HashMap 一起使用(并以LRU缓存方式进行) 检索/更新将是o(1)。 排名前10的结果将是列表中的项目。
双重列表的结构:
class UrlAndCountNode{
String url;
int count;
UrlAndCountNode next;
UrlAndCountNode prev;
}
地图结构:
Map<String, UrlAndCountNode>
答案 4 :(得分:0)
这是一个有趣的问题IMO。您似乎需要点击sorted
的内容,但同时您需要更改这些值,使用数据结构执行此操作的唯一方法是删除该条目(您要更新)和把更新后的那个放回去。简单地更新clicks
将无效。因此,我认为保持按点击排序是一个更好的选择。
缺点是,如果有相同点击次数的条目,它们将被覆盖,因为像guava multiset
这样的东西将是一个更好的选择。
因此我会这样做:
static class Holder {
private final String name;
private final int clicks;
public Holder(String name, int clicks) {
super();
this.name = name;
this.clicks = clicks;
}
public String getName() {
return name;
}
public int getClicks() {
return clicks;
}
@Override
public String toString() {
return "name = " + name + " clicks = " + clicks;
}
}
方法看起来像这样:
private static List<Holder> firstN(Multiset<Holder> set, int n) {
return set.stream().limit(n).collect(Collectors.toList());
}
private static void updateOne(Multiset<Holder> set, String urlName, int more) {
Iterator<Holder> iter = set.iterator();
int currentClicks = 0;
boolean found = false;
while (iter.hasNext()) {
Holder h = iter.next();
if (h.getName().equals(urlName)) {
currentClicks = h.getClicks();
iter.remove();
found = true;
}
}
if (found) {
set.add(new Holder(urlName, currentClicks + more));
}
}