I tried this,
public class Solution {
public string FrequencySort(string s) {
var dict = new Dictionary<char, int>();
foreach (char c in s) {
if (dict.ContainsKey(c)) dict[c]++;
else dict[c] = 1;
}
var pq = new PriorityQueue<char, (int f, int o)>(Comparer<(int, int)>.Create((a, b) => b.CompareTo(a)));
foreach (char c in s) {
pq.Enqueue(c, (dict[c], c - 'a'));
}
var sb = new StringBuilder();
while (pq.Count > 0) {
sb.Append(pq.Dequeue());
}
return sb.ToString();
}
}We get frequencies in dict. We make max heap with tuple priority (freq and ‘order alphabetical’ kind of).
Then, we enqueue each char in s in the heap. Value is char itself, priority is tuple of freq and character order alphabetically (so keep same characters together).
Then we dequeue it all.
Something better,
public class Solution {
public string FrequencySort(string s) {
var freq = new Dictionary<char, int>();
foreach (char c in s)
freq[c] = freq.GetValueOrDefault(c) + 1;
var pq = new PriorityQueue<char, int>(
freq.Select(kv => (kv.Key, kv.Value)),
Comparer<int>.Create((a, b) => b.CompareTo(a))); // max-heap by frequency
var sb = new StringBuilder();
while (pq.TryDequeue(out var c, out var count))
sb.Append(c, count); // append c, count times
return sb.ToString();
}
}First, we only keep distinct chars in heap. And in dequeue, we append as many times as count.