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

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

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

  1. @Data
  2. public class MovieFrequencyTuple implements Comparable<MovieFrequencyTable> {
  3. @NonNull private final String name;
  4. private int frequency;
  5. public void incrementFrequency() {
  6. frequency++;
  7. }
  8. @Override public int compareTo(MovieFrequencyTuple other) {
  9. int c = Integer.compare(frequency, other.frequency);
  10. if (c != 0) return -c;
  11. return name.compareTo(other.name);
  12. }
  13. }

有了这些:

  1. SortedSet<MovieFrequencyTuple> frequencies = new TreeSet<>();
  2. Map<String, MovieFrequencyTuple> movies = new HashMap<>();
  3. public int increment(String movieName) {
  4. MovieFrequencyTuple tuple = movies.get(name);
  5. if (tuple == null) {
  6. tuple = new MovieFrequencyTuple(name);
  7. movies.put(name, tuple);
  8. }
  9. // Self-sorting data structures will just fail
  10. // to do the job if you modify a sorting order on
  11. // an object already in the collection. Thus,
  12. // we take it out, modify, put it back in.
  13. frequencies.remove(tuple);
  14. tuple.incrementFrequency();
  15. frequencies.add(tuple);
  16. return tuple.getFrequency();
  17. }
  18. public int get(String movieName) {
  19. MovieFrequencyTuple tuple = movies.get(movieName);
  20. if (tuple == null) return 0;
  21. return tuple.getFrequency();
  22. }
  23. public List<String> getTop10() {
  24. var out = new ArrayList<String>();
  25. for (MovieFrequencyTuple tuple : frequencies) {
  26. out.add(tuple.getName());
  27. if (out.size() == 10) break;
  28. }
  29. return out;
  30. }

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

展开查看全部

相关问题