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.




// correct
class Solution {
public String frequencySort(String s) {
// use some data struc to store the freq
HashMap<Character, Integer> map = new HashMap<>();
for(Character c : s.toCharArray()){
if(!map.containsKey(c)){
map.put(c, 1);
}else{
map.put(c, map.get(c) + 1);
}
}
StringBuilder sb = new StringBuilder();
// put the map entry into a max heap , accroding to the freq
// pop all, add it to the string
PriorityQueue<Map.Entry<Character, Integer>> pq = new PriorityQueue<>((a1, a2) -> a2.getValue().compareTo(a1.getValue())); // lambda expression, getValue(), a2.compareTo(a1) is maxHeap
for(Map.Entry<Character, Integer> entry: map.entrySet()){ // Map.Entry<> , map.entrySet()
pq.offer(entry);
}
while(!pq.isEmpty()){
Map.Entry<Character, Integer> entry = pq.poll(); // can only poll once, Map.Entry<>
char c = entry.getKey();
int freq = entry.getValue();
while(freq > 0){ // append freq times
sb.append(c);
freq--;
}

}
return sb.toString();
// still not familiar with the map entry set, and get value () ? and the entry set in max heap
// and lambda expression for custom comparison
// for (Map.Entry<String, String> entry : map.entrySet())

// System.out.println(entry.getKey() + "/" + entry.getValue());

// https://dzone.com/articles/using-lambda-expression-sort
// personList.sort((p1, p2) -> p1.firstName.compareTo(p2.firstName));

// PriorityQueue<Integer> pq = new PriorityQueue<>((x, y) -> y - x);



}
}