通常使用trie和堆的组合来解决在书中找到k个最常用单词的常见问题(可以动态添加单词)。
但是,我认为即使使用TreeSet也应该足够,并且对于插入和检索具有log(n)性能。
treeset将包含一个自定义对象:
class MyObj implements Comparable{
String value;
int count;
public int incrementCount(){count++;}
//override equals and hashcode to make this object unique by string 'value'
//override compareTo to compare count
}
每当我们在树集中插入对象时,我们首先检查该元素是否已经存在于树集中,如果是,那么我们得到obj并递增该对象的count变量。
每当我们想要找到k个最大的单词时,我们只是迭代树集的前k个元素
您对上述方法有何看法?我觉得这种方法更容易编码和理解,并且还匹配trie和heap方法的时间复杂度以获得k个最大元素
编辑:如其中一个答案中所述,在插入myobj之后递增计数变量不会对树集/树形图进行重新排序。因此,在递增计数后,我还需要删除并重新插入treeset / treemap中的对象
答案 0 :(得分:2)
将对象输入TreeSet
后,如果compareTo
方法的比较中使用的属性发生更改,则TreeSet
(或基础TreeMap
)< em>不重新排序元素。因此,这种方法不能按预期工作。
这是一个演示它的简单示例
public static class MyObj implements Comparable<MyObj> {
String value;
int count;
MyObj(String v, int c) {
this.value = v;
this.count = c;
}
public void incrementCount(){
count++;
}
@Override
public int compareTo(MyObj o) {
return Integer.compare(this.count, o.count); //This does the reverse. Orders by freqency
}
}
public static void main(String[] args) {
Set<MyObj> set = new TreeSet<>();
MyObj o1 = new MyObj("a", 1);
MyObj o2 = new MyObj("b", 4);
MyObj o3 = new MyObj("c", 2);
set.add(o1);
set.add(o2);
set.add(o3);
System.out.println(set);
//The above prints [a-1, c-2, b-4]
//Increment the count of c 4 times
o3.incrementCount();
o3.incrementCount();
o3.incrementCount();
o3.incrementCount();
System.out.println(set);
//The above prints [a-1, c-6, b-4]
正如我们所看到的,c-6
对应的对象没有被推到最后。
//Insert a new object
set.add(new MyObj("d", 3));
System.out.println(set);
//this prints [a-1, d-3, c-6, b-4]
}
修改强>
的注意事项/问题:强>
count
,如果两个单词具有相同的频率,则会删除一个单词。因此,如果频率相同,则需要比较实际的单词。MyObj
获取该对象(指定value
TreeSet
实例以了解到目前为止的频率)。集合没有get
方法。其contains
方法仅委托给基础TreeMap's
containsKey
方法,该方法使用compareTo
逻辑(而不是equals
)来标识对象。 compareTo函数还考虑了单词的频率,因此我们无法识别集合中的单词以将其删除(除非我们在每次添加时迭代整个集合)答案 1 :(得分:1)
如果删除并插入对象,TreeMap应该有效,使用整数键作为频率,将MyObj列表作为值,键按频率排序。上述代码的更新证明了这一点:
public class MyObj {
String value;
int count;
MyObj(String v, int c) {
this.value = v;
this.count = c;
}
public int getCount() {
return count;
}
public void incrementCount() {
count++;
}
@Override
public String toString() {
return value + " " + count;
}
public static void put(Map<Integer, List<MyObj>> map, MyObj value) {
List<MyObj> myObjs = map.get(value.getCount());
if (myObjs == null) {
myObjs = new ArrayList<>();
map.put(value.getCount(),myObjs);
}
myObjs.add(value);
}
public static void main(String[] args) {
TreeMap<Integer, List<MyObj>> set = new TreeMap<>();
MyObj o1 = new MyObj("a", 1);
MyObj o2 = new MyObj("b", 4);
MyObj o3 = new MyObj("c", 2);
MyObj o4 = new MyObj("f", 4);
put(set,o1);
put(set,o2);
put(set,o3);
System.out.println(set);
put(set,o4);
System.out.println(set);
}
}