【刷题】1366. 通过投票对团队排名(Rank Teams by Votes)

题目

现在有一个特殊的排名系统,依据参赛团队在投票人心中的次序进行排名,每个投票者都需要按从高到低的顺序对参与排名的所有团队进行排位。

排名规则如下:

参赛团队的排名次序依照其所获「排位第一」的票的多少决定。如果存在多个团队并列的情况,将继续考虑其「排位第二」的票的数量。以此类推,直到不再存在并列的情况。
如果在考虑完所有投票情况后仍然出现并列现象,则根据团队字母的字母顺序进行排名。
给你一个字符串数组 votes 代表全体投票者给出的排位情况,请你根据上述排名规则对所有参赛团队进行排名。

请你返回能表示按排名系统 排序后 的所有团队排名的字符串。

示例 1:
输入:votes = [“ABC”,“ACB”,“ABC”,“ACB”,“ACB”]
输出:“ACB”
解释:A 队获得五票「排位第一」,没有其他队获得「排位第一」,所以 A 队排名第一。
B 队获得两票「排位第二」,三票「排位第三」。
C 队获得三票「排位第二」,两票「排位第三」。
由于 C 队「排位第二」的票数较多,所以 C 队排第二,B 队排第三。

来源:力扣(LeetCode)https://leetcode-cn.com/problems/rank-teams-by-votes

思路

AC后去看官方题解,很开心,总算和题解一个思路了。
这个题目和小时候收集小浣熊三国英雄卡片一样,用武力值来对武将排序。后面又要求当各个名次的票数一致时,要根据队伍名字来进行排序。
看完这个要求,拿Java作为吃饭家伙的我,能想象到的只有Collections.sort来对整个排序这种方式了,自己写排序算法太麻烦了。
为了方便些比较器,我们需要先定义个Team类,里面有两个成员变量,一个是名字,为了方便比较我直接用int来表示,构造时用队名-‘A’来表示;另一个是各个名次的票数数组。

class Team {
    int name;
    int[] votes;

    public Team(int name, int[] votes) {
        this.name = name;
        this.votes = votes;
    }
}

然后的事情就很简单了,首先是将所有的投票遍历,存储数据到一个List中去,为了方便根据队名取出对应的票数,我们用个Map来讲队名和Team对象映射。最后根据规则写一个比较器,然后输出结果即可。

public String rankTeams(String[] votes) {
    if (votes == null) {
        return null;
    }
    // 队伍总数
    int teamNum = votes[0].length();
    List<Team> teams = new ArrayList<>(teamNum);
    Map<Character, Team> teamMap = new HashMap<>(teamNum);
    // 遍历票数,存储数据
    for (String vote : votes) {
        for (int i = 0; i < vote.length(); i++) {
            char teamName = vote.charAt(i);
            Team team = teamMap.get(teamName);
            if (team == null) {
                // team为空说明是第一次读取,需要初始化一下数据
                team = new Team((int) (teamName - 'A'), new int[teamNum]);
                teams.add(team);
                teamMap.put(teamName, team);
            }
            // 在该队伍的第i名次上计数加一
            team.votes[i]++;
        }
    }
    // 用比较器来做排序,票数降序,队名升序
    Collections.sort(teams, new Comparator<Team>() {
        @Override
        public int compare(Team team, Team t1) {
            int len = team.votes.length;
            // 名次票数降序,用第二个减第一个
            for (int i = 0; i < len; i++) {
                if (team.votes[i] != t1.votes[i]) {
                    return t1.votes[i] - team.votes[i];
                }
            }
            // 队名升序,用第一个减第二个
            return team.name - t1.name;
        }
    });
    StringBuilder ans = new StringBuilder();
    for (Team team : teams) {
        ans.append((char) ('A' + team.name));
    }
    return ans.toString();
}

知识点

这里用到了Java集合中的比较器,一直记不清升序降序的写法。反复试验后,强行记一下:“升序前减后,降序后减前”。
详细解释,我再去查查源码然后更新一下,晚安~

发布了24 篇原创文章 · 获赞 13 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/kiba_zwei/article/details/105258845