【问题标题】:Using TreeMap to find max elements使用 TreeMap 查找最大元素
【发布时间】:2014-11-16 19:27:40
【问题描述】:

我正在设计棒球联盟前 5 名击球手的记分牌。我使用TreeMapplayer_name 作为valuePlayer 作为key

Map<Player, String> players  = new TreeMap<>(Collections.reverseOrder());

Player 班级按照联盟中的得分进行自然排序 compare(this.leagueRuns, otherPlayer.leagueRuns)

leagueRuns 在比赛期间不断更新,前 5 名击球手记分牌也应相应更改。下面是更新球员联赛并重新插入TreeMap 的代码。更新后,检索并显示 Map 中的 TOP 5 条目。

 public void updateRuns(String playerName, int runsScored) {

            Iterator<Entry<Player, String>> playersEntries = players.entrySet().iterator();

            Player player = null;
            while (playersEntries.hasNext()) {
                Entry<Player, String> currentPlayer = playersEntries.next();
                if (currentPlayer.getValue().equalsIgnoreCase(playerName)) {
                    player = currentPlayer.getKey();
                }
            }
            players.remove(player);
            player.addRuns(runsScored);
            players.put(player, player.getName());        
 }

一切正常,但我有以下顾虑:

  1. 为了对Player 进行排序,我在TreeMap 中将其用作Key。但是必须遍历整个Map 才能找到正在更新的Player。因此时间复杂度从 O(1) 降低到 O(n)。并且变得更糟,因为我必须删除 Player,更新它并重新插入,否则更改将不会生效。因此O(n + logn)。有没有办法按照自然顺序对Player 进行排序,并且还能够在 O(1) 中进行搜索。我想重新插入是不可避免的。
  2. 每次为玩家更新leagueRuns,都必须重新订购整个TreeMap。你认为创建一个单独的 TOP 5 击球手最小堆可以解决这个问题并且是一个可行的想法。
  3. 有关设计或提高时间复杂度的任何提示。

【问题讨论】:

  • @DavidWallace 搜索和更新Player 可以使用 `HashMap 在 O(1) 中完成。但是构建一个单独的最高得分者列表的总成本将是 O(nlogn)。

标签: java data-structures heap time-complexity treemap


【解决方案1】:

你应该支持两种结构:

  1. 快速播放器搜索(名称 => 播放器),例如HashMap
  2. 记分牌的排序结构(玩家和分数),例如树集

所以更新记分板将是 O(log(N)):

Map<String, Player> players;
SortedSet<Player> scoreboard;

public void updateRuns(String playerName, int runsScored) {
    Player player = players.get(playerName);
    if (player == null) {
        player = new Player(playerName, runsScored);
    } else {
        scorepoard.remove(player);
        player.addRuns(runsScored);
    }
    scoreboard.add(player);
}

如果您使 Player 类不可修改(首选方式),您将得到相同的 O(log(N)):

public void updateRuns(String playerName, int runsScored) {
    Player player = players.remove(playerName);
    if (player == null) {
        player = new Player(playerName, runsScored);
    } else {
        scorepoard.remove(player);
        player = new Player(playerName, player.getRuns() + runsScored);
    }
    players.put(playerName, player);
    scoreboard.add(player);
}

【讨论】:

  • 这是正确的解决方案,也是唯一真正明智的做法。 +1。
  • 想知道(玩家人数)是否很大,比如说 > 10^6。在两个数据结构中保留Player 对象会导致数据冗余。
  • 其实没有数据重复。数据结构需要只保留 结构 以便快速访问。如果您有 10^6 个玩家,那么您将在内存中拥有 10^6 个玩家条目 + HashMap(N=10^6) 结构 + TreeSet(N=10^6) 结构。
猜你喜欢
  • 2016-11-26
  • 2015-03-11
  • 1970-01-01
  • 1970-01-01
  • 2021-07-02
  • 1970-01-01
  • 2020-05-08
  • 2014-07-21
相关资源
最近更新 更多