โจทย์: Sort Characters By Frequency
ให้สตริง s ต้องเรียงตัวอักษรตาม ความถี่จากมากไปน้อย** หากความถี่เท่ากัน ลำดับไม่ได้ระบุ (แต่โค้ดตัวอย่างเรียงตาม ASCII)
ตัวอย่าง: s = "abbbacbcc"
ความถี่: b:4, c:3, a:2
ผลลัพธ์: "bbbbcccaa"
อัลกอริทึม: Counting + Sorting
- นับความถี่แต่ละตัวอักษรด้วย
unordered_map<char, int>หรือ array[256] - เก็บคู่
(frequency, character)ลงใน vector - เรียง vector ตาม frequency มากไปน้อย (descending)
- สร้างสตริงผลลัพธ์โดยทำซ้ำตัวอักษรตามความถี่
ตัวอย่างโค้ด C++
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
static bool cmp(const pair<int, char>& a, const pair<int, char>& b) {
return a.first > b.first; // เรียง frequency มากไปน้อย
}
string frequencySort(string s) {
unordered_map<char, int> freq;
for (char c : s) freq[c]++;
vector<pair<int, char>> v;
for (auto& p : freq) {
v.push_back({p.second, p.first});
}
sort(v.begin(), v.end(), cmp);
string ans;
for (auto& p : v) {
ans.append(p.first, p.second); // append(char, count)
}
return ans;
}
};
int main() {
Solution ob;
cout << ob.frequencySort("abbbacbcc") << endl;
return 0;
}
Input
"abbbacbcc"
Output
bbbbcccaa
ความซับซ้อน (Complexity)
- เวลา: O(n + k log k) โดย n = ความยาวสตริง, k = จำนวนตัวอักษรที่แตกต่างกัน (≤ 256)
- พื้นที่: O(k)
วิธีอื่น (Bucket Sort) O(n): เนื่องจาก frequency สูงสุด = n สร้าง bucket[ n+1 ] เก็บตัวอักษรที่มีความถี่เท่ากัน แล้ววนจาก n ลง 0
// Bucket Sort version O(n)
string frequencySort(string s) {
vector<int> freq(256, 0);
for (char c : s) freq[c]++;
vector<vector<char>> bucket(s.size() + 1);
for (int i = 0; i < 256; i++) {
if (freq[i] > 0) bucket[freq[i]].push_back(char(i));
}
string ans;
for (int f = s.size(); f >= 1; f--) {
for (char c : bucket[f]) {
ans.append(f, c);
}
}
return ans;
}
แก้ไขจากโค้ดต้นฉบับ: โค้ดต้นฉบับใช้ map (ซึ่งเรียงตาม key อัตโนมัติ) และ sort(v.rbegin(), v.rend(), cmp) ซึ่งซับซ้อนเกินไป ได้ลดรูปให้ชัดเจนกว่า