我正在尝试使用Java树集解决算法问题。
问题如下:
Find top k frequent words in realtime data stream.
Implement three methods for Topk Class:
TopK(k). The constructor.
add(word). Add a new word.
topk(). Get the current top k frequent words.
我的想法是使用哈希图记住频率,并使用树集作为缓冲区。
我的实现通过了大多数情况,除了以下一种情况:
TopK(10)
add("aw")
add("fb")
add("fb")
topk()
答案应该是[fb,aw],但现在是[fb,aw,fb] 但是,我的代码通过了以下测试用例:
TopK(10)
add("iiiiii")
add("fb")
add("fb")
topk()
和
TopK(10)
add("fb")
add("fb")
topk()
我不知道怎么了,所以在调用比较器时我打印了一些值。它给了我这个:
aw aw
11111111
fb aw
33333333
fb aw
33333333
fb aw
222222222
fb aw
222222222
这意味着将第二个“ fb”与“ aw”进行两次比较,然后完成比较器。我花了几个小时进行调试,但到目前为止我什么都没发现。
这是我的实现方式:
public class TopK {
int size;
HashMap<String, Integer> map;
TreeSet<String> seen;
public TopK(int k) {
// do intialization if necessary
size = k;
seen = new TreeSet<String>(new Comparator<String>(){
@Override
public int compare(String str1, String str2){
System.out.println(str1 + " "+ str2);
if (str1.equals(str2)){
System.out.println("11111111");
return 0;
}
// important !https://www.jiuzhang.com/qa/7646/
// 128 以后integer就不同了
int number1 = map.get(str1);
int number2 = map.get(str2);
if (number1 != number2){
System.out.println("222222222");
return map.get(str1) - map.get(str2);
} else {
System.out.println("33333333");
return str2.compareTo(str1);
}
}
});
map = new HashMap<String, Integer>();
}
/*
* @param word: A string
* @return: nothing
*/
public void add(String word) {
// write your code here
if (!map.containsKey(word)){
map.put(word, 0);
}
map.put(word, map.get(word) + 1);
if (seen.contains(word)){
seen.remove(word);
seen.add(word);
} else {
seen.add(word);
if (seen.size() > size){
seen.pollFirst();
}
}
}
/*
* @return: the current top k frequent words.
*/
public List<String> topk() {
// Write your code here
List<String> results = new ArrayList<String>();
Iterator it = seen.iterator();
while(it.hasNext()) {
String str = (String)it.next();
results.add(0, str);
}
return results;
}
}
答案 0 :(得分:1)
我们的第一个线索就是这种情况:
aw
fb
fb
失败,但是:
iiiii
fb
fb
成功。
只能由于以下行而发生这种情况:return str2.compareTo(str1);
-如果出现的数量按字符串比较顺序不同(可以很容易地检查-请这样做)。
我能想到的唯一解释是java TreeSet的contains
函数具有“优化”功能,仅在元素应位于的位置进行搜索-如果您有顺序并且元素不在应放置的位置,则考虑就像TreeSet中不存在那样(想想应该检查log(n)中运行的数字的数组,而不是所有数组上的数组-如果他以错误的位置存在,您会想念他的。)
请注意,在检查contains
函数之前,您更改了元素应放置的位置。因此,让我们看一下第二次迭代-在地图中我们有fb
和aw
的值均为1。在TreeSet上,它们为[fb,aw]
(因为字符串比较如前所述)。现在,您更改地图,fb
的值为2->它应该排在最后,但是contains
函数与aw
相比并认为应该在它之后-但是他是最后一个元素,因此假定fb
不存在,只需添加他->为什么您看到 2 在fb
和aw
之间进行比较-一个用于{ {1}}和一个contain
。
希望是可以理解的......