1. 程式人生 > >[LeetCode] Sort Characters By Frequency 根據字元出現頻率排序

[LeetCode] Sort Characters By Frequency 根據字元出現頻率排序

Given a string, sort it in decreasing order based on the frequency of characters.

Example 1:

Input:
"tree"

Output:
"eert"

Explanation:
'e' appears twice while 'r' and 't' both appear once.
So 'e' must appear before both 'r' and 't'. Therefore "eetr" is also a valid answer.

Example 2:

Input:
"cccaaa"

Output:
"cccaaa"

Explanation:
Both 'c' and 'a' appear three times, so "aaaccc" is also a valid answer.
Note that "cacaca" is incorrect, as the same characters must be together.

Example 3:

Input:
"Aabb"

Output:
"bbAa"

Explanation:
"bbaA" is also a valid answer, but "Aabb" is incorrect.
Note that 'A' and 'a' are treated as two different characters.

這道題讓我們給一個字串按照字元出現的頻率來排序,那麼毫無疑問肯定要先統計出每個字元出現的個數,那麼之後怎麼做呢?我們可以利用優先佇列的自動排序的特點,把個數和字元組成pair放到優先佇列裡排好序後,再取出來組成結果res即可,參見程式碼如下:

解法一:

class Solution {
public:
    string frequencySort(string s) {
        string res = "";
        priority_queue<pair<int, char>> q;
        unordered_map
<char, int> m; for (char c : s) ++m[c]; for (auto a : m) q.push({a.second, a.first}); while (!q.empty()) { auto t = q.top(); q.pop(); res.append(t.first, t.second); } return res; } };

我們也可以使用STL自帶的sort來做,關鍵就在於重寫comparator,由於需要使用外部變數,記得中括號中放入&,然後我們將頻率大的返回,注意一定還要處理頻率相等的情況,要不然兩個頻率相等的字元可能穿插著出現在結果res中,這樣是不對的。參見程式碼如下:

解法二:

class Solution {
public:
    string frequencySort(string s) {
        unordered_map<char, int> m;
        for (char c : s) ++m[c];
        sort(s.begin(), s.end(), [&](char& a, char& b){
            return m[a] > m[b] || (m[a] == m[b] && a < b);
        });
        return s;
    }
};

我們也可以不使用優先佇列,而是建立一個字串陣列,因為某個字元的出現次數不可能超過s的長度,所以我們將每個字元根據其出現次數放入陣列中的對應位置,那麼最後我們只要從後往前遍歷陣列所有位置,將不為空的位置的字串加入結果res中即可,參見程式碼如下:

解法三:

class Solution {
public:
    string frequencySort(string s) {
        string res = "";
        vector<string> v(s.size() + 1, "");
        unordered_map<char, int> m;
        for (char c : s) ++m[c];
        for (auto& a : m) {
            v[a.second].append(a.second, a.first);
        }
        for (int i = s.size(); i > 0; --i) {
            if (!v[i].empty()) {
                res.append(v[i]);
            }
        }
        return res;
    }
};

類似題目:

參考資料: