class Solution {
public:
// Used for making a max priority queue, based on the second number in the pair.
struct myComp {
constexpr bool operator()(
pair<char, int> const& a,
pair<char, int> const& b)
const noexcept
{
return a.second < b.second;
}
};
int leastInterval(vector<char>& tasks, int n) {
// a map of the count per each task
unordered_map<char, int> countPerTask{};
for (char curTask : tasks)
{
if (countPerTask.find(curTask) == countPerTask.end())
{
countPerTask.insert({curTask, 0});
}
++countPerTask[curTask];
}
// vector of pairs of tasks and their counts. Used to make priority queue.
vector<pair<char, int>> tasksAndTheirCounts{};
for (const auto& taskAndCount : countPerTask)
{
tasksAndTheirCounts.push_back(taskAndCount);
}
// Will be putting tasks in this vector.
vector<char> ans{};
// max heap priority queue. pairs are in decreasing order based on the task's count.
priority_queue<pair<char,int>, vector<pair<char, int>>, myComp> pq(tasksAndTheirCounts.begin(), tasksAndTheirCounts.end());
// for each iteration run through n letters.
while(!pq.empty())
{
// keeps the seen tasks and count
unordered_map<char, int> seen{};
// Run through n letters. If number of letters runs out, then add 'i' to indicate idle.
// Or if number of letters runs out, it may be that we've run out of letters, then break!
for (int ii=0; ii<=n; ++ii)
{
if (pq.empty())
{
if (seen.size() == 0)
{
break;
}
else
{
ans.push_back('i');
}
}
else
{
// always use the letter that has the largest count first.
pair<char, int> topPair = pq.top();
pq.pop();
char topChar = topPair.first;
int topCount = topPair.second;
if (topCount > 1)
{
seen.insert({topChar, topCount-1});
}
ans.push_back(topChar);
}
}
// for next iteration add back the used letters in seen. Realize, they're being added back in with
// one lest count.
for (const auto& seenWithCount : seen)
{
pq.push(seenWithCount);
}
}
return ans.size();
}
};