Leetcode 1366. Rank Teams by Votes (python+cpp)

题目

Leetcode 1366. Rank Teams by Votes (python+cpp)_第1张图片
这题看起来不难,但实际上有挺多启发点的

错误解法:

这题有个理解误区,一开始以为是按照分数来排序。比如第一位得五分,第二位的四分这样,把所有的字符分数计算出来然后排序,于是就有了下面的错误解法

class Solution {
     
public:
    string rankTeams(vector<string>& votes) {
     
        vector<pair<int,int>> scores(26,{
     0,0});
        int n = votes[0].size();
        for(auto vote : votes){
     
            for(int i=0;i<n;i++){
     
                scores[vote[i]-'A'].first -= n-i;
                scores[vote[i]-'A'].second = vote[i]-'A';
            }
        }
        sort(scores.begin(),scores.end());
        string ans = "";
        for(auto score : scores){
     
            if(!score.first) continue;
            ans += (score.second+'A');
        }
        return ans;
        
    }
};

解法1:

但再看题意,其实这样理解是错的。题目的意思是按照从前往后的比较顺序,有点像字典序,而不是以最后的分解过来比较这样。一旦按顺序某一位不相等,比较就会立即结束,而不是以某个字符的总得分来比较。
所以新的解法是这样的,建立一个二维数组,每一行代表的是某个字符的ranking统计,每一行的i位置的值代表该字符被投为第i名的次数。然后按照行跟行之间的相互大小关系来进行排序。但是由于排完序之后某行代表哪个字符没有办法确定,所以在每一行的最后添加改行代表字符的ascii值,这样排序后我们可以retrieve某一行代表哪个字符了。
然后自以为这题的关键就是自定义行跟行的比较,在C++里面也就是比较两个vector需要自定义operator,于是就有了下面的解法

class Solution {
     
    static bool cmp(const vector<int>& a, const vector<int>& b){
     
        for(int i=0;i<a.size();i++){
     
            if(a[i] < b[i]){
     
                return true;
            }else if(a[i] > b[i]){
     
                return false;
            }
        }
        return false;
    }
public:
    string rankTeams(vector<string>& votes) {
     
        vector<vector<int>> ranks(26,vector<int>(27,0));
        for(auto c : votes[0]){
     
            ranks[c-'A'][26] = c;
        }
        
        for(auto vote : votes){
     
            for(int i=0;i<vote.size();i++){
     
                ranks[vote[i]-'A'][i] -= 1;
            }
        }
        sort(ranks.begin(),ranks.end(),cmp);
        string res;
        for(int i=0;i<votes[0].size();i++){
     
            res += ranks[i][26];
        }
        return res;
        
    }
};

解法2:

解法1自然是能过得,但是后来看到网上有的解法居然不需要自定义operator???我之前是一直以为vector是没有default comparator的,但事实证明vector有默认的比较器,只不过是按照字典序来比较vector
参考:https://stackoverflow.com/questions/59668278/sorting-vector-of-vectors-without-comparator-or-lambda-function

class Solution {
     
public:
    string rankTeams(vector<string>& votes) {
     
        vector<vector<int>> ranks(26,vector<int>(27,0));
        for(auto c : votes[0]){
     
            ranks[c-'A'][26] = c;
        }
        
        for(auto vote : votes){
     
            for(int i=0;i<vote.size();i++){
     
                ranks[vote[i]-'A'][i] -= 1;
            }
        }
        sort(ranks.begin(),ranks.end());
        string res;
        for(int i=0;i<votes[0].size();i++){
     
            res += ranks[i][26];
        }
        return res;
        
    }
};

C++版本这边注意char和int之间是有默认转化的,而且字符本来就是直接以ascii码的int值储存的。所以写起来很方便,python就要用ord()和chr()了

python版本:
python可以直接用字典代替vector,这样更节省空间,c++是因为unordered_map的value并不能是vector,所以用矩阵表示更方便

class Solution:
    def rankTeams(self, votes: List[str]) -> str:
        ranks = {
     v:[0]*len(votes[0])+[v] for v in votes[0]}
        for vote in votes:
            for i,c in enumerate(vote):
                ranks[c][i] -= 1;
        
        tmp = list(votes[0])
        tmp.sort(key = lambda x:ranks[x])
        return "".join(tmp)

你可能感兴趣的:(Leetcode,排序,Leetcode,其他类型题目,c++,python,leetcode)