我应该用bucketsort或heapsort对包含频率的hashmap进行排序吗?

nkcskrwz  于 2021-07-06  发布在  Java
关注(0)|答案(1)|浏览(364)

我有一个java格式的hashmap HashMap<String, Integer> frequency . 键是一个字符串,我在其中保存电影的名称,值是所说电影的频率。
我的程序接受用户的输入,所以每当有人把视频添加到收藏夹时,我就进入hashmap并增加它的频率。
现在的问题是,在某一点上,我需要采取最k频繁的电影。我发现我可以在这个leetcode问题中使用bucketsort或heapsort(查看第一个注解),但是我不确定在我的例子中它是否更有效。我的hashmap不断更新,因此如果一个频率发生变化,我需要再次调用排序算法。
根据我的理解,构建Map需要o(n)个时间,其中“n”是电影的数量,即使有重复的电影,因为它需要增加频率,这就得到了我独特的电影标题。这是否意味着heapsort会对任何给定的k产生o(m*log(k))和bucketsort o(m)?

20jt8wwn

20jt8wwn1#

不幸的是,拥有一个按值排序的Map(Map到的对象)不是一件事。相反,您可以有一个键集,它的键按频率排序,但是如果频率是该点的键,那么在事先不知道频率的情况下,就无法在该集中查找条目,这样就消除了练习的重点。
想到的一个策略是有两个独立的数据结构。一种是根据电影名称查找实际对象,另一种是自动排序:

@Data
public class MovieFrequencyTuple implements Comparable<MovieFrequencyTable> {
    @NonNull private final String name;
    private int frequency;

    public void incrementFrequency() {
        frequency++;
    }

    @Override public int compareTo(MovieFrequencyTuple other) {
        int c = Integer.compare(frequency, other.frequency);
        if (c != 0) return -c;
        return name.compareTo(other.name);
    }
}

有了这些:

SortedSet<MovieFrequencyTuple> frequencies = new TreeSet<>();
Map<String, MovieFrequencyTuple> movies = new HashMap<>();

public int increment(String movieName) {
    MovieFrequencyTuple tuple = movies.get(name);
    if (tuple == null) {
        tuple = new MovieFrequencyTuple(name);
        movies.put(name, tuple);
    }

    // Self-sorting data structures will just fail
    // to do the job if you modify a sorting order on
    // an object already in the collection. Thus,
    // we take it out, modify, put it back in.
    frequencies.remove(tuple);
    tuple.incrementFrequency();
    frequencies.add(tuple);
    return tuple.getFrequency();
}

public int get(String movieName) {
    MovieFrequencyTuple tuple = movies.get(movieName);
    if (tuple == null) return 0;
    return tuple.getFrequency();
}

public List<String> getTop10() {
   var out = new ArrayList<String>();
   for (MovieFrequencyTuple tuple : frequencies) {
       out.add(tuple.getName());
       if (out.size() == 10) break;
   }
   return out;
}

每一个操作都要摊销o(1)或o(logn),甚至是前10个操作。因此,如果你运行100万次“增加一部电影的频率,然后获得前10名”,n=#我们这样做的次数,那么最坏的情况是o(nlogn)性能。
注意:将lombok用于构造函数、getter等-如果您不喜欢,请让您的ide生成这些东西。

相关问题