Search code examples
javadata-structuresheaptime-complexitytreemap

Using TreeMap to find max elements


I am designing a Baseball League scoreboard of TOP 5 Batsmen. I am using a TreeMap with player_name as value and Player as key.

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

Player class has natural ordering as per runs scored in the league compare(this.leagueRuns, otherPlayer.leagueRuns)

leagueRuns are updated contantly during the game and the TOP 5 Batsmen scoreboard should also change accordingly. Below is the code to update league runs for a player and re-insertion into TreeMap. After updating, TOP 5 entries from Map are retrieved and displayed.

 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());        
 }

Everything is working fine but I have following concerns:

  1. In order to sort Player I am using it as Key in TreeMap. But have to iterate through the whole Map to find Player being updated. Hence time complexity degraded from O(1) to O(n). And gets even worse as I have to remove that Player, update it and re-insert otherwise changes won't take effect. Hence O(n + logn). Is there a way to sort Player as per natural ordering and also be able to search in O(1). I guess re-insertion cannot be avoided.
  2. Every time leagueRuns is updated for a player, the whole TreeMap has to be re-ordered. Do you think creating a separate min-heap of TOP 5 Batsmen can resolve this issue and is a viable idea.
  3. Any tips on design or improving time complexity.

Solution

  • You should support 2 structures:

    1. quick player search (name => Player), e.g. HashMap<String, Player>
    2. sorted structure for scoreboard (Player & score), e.g. TreeSet<Player>

    So update scoreboard will be 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);
    }
    

    If you make Player class unmodifiable (preferred way), you'll get the same 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);
    }