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

努利!奮鬥!發表於2021-01-03

題目

在這裡插入圖片描述
這題看起來不難,但實際上有挺多啟發點的

錯誤解法:

這題有個理解誤區,一開始以為是按照分數來排序。比如第一位得五分,第二位的四分這樣,把所有的字元分數計算出來然後排序,於是就有了下面的錯誤解法

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)

相關文章