PriorityQueue
Reorganize String
给一个string, 需要重新生成一个新的string, 要求相邻两个char不能重复
可以把input转化成charToCnt dict, 然后存成node, key is char, val is cnt
建一个maxHeap, sort by cnt
每次从maxHeap中pop一个 candidate1, 如果candidate1.val == prevChar, 则需要再pop一个candidate2
class Solution {
/*
Node-> (char, cnt)
maxHeap<Node> sort by cnt
every time pop 2 elements from maxHeap, candidate1 and candidate2
keep track of prevChar
if both candidate1 and candidate1 are same as prevChar, then means cannot reorganzie to a new string
improvement:
we don't really need to pop 2 element every time, just when cur element is same as prev, then pop 2nd one.
*/
public class Node {
char val;
int cnt;
public Node(char val, int cnt) {
this.val = val;
this.cnt = cnt;
}
}
public String reorganizeString(String S) {
if (S== null || S.length() == 0) return "";
Map<Character, Integer> charToCnt = new HashMap<>();
for (char c : S.toCharArray()) {
int cnt = charToCnt.getOrDefault(c, 0);
charToCnt.put(c, cnt + 1);
}
PriorityQueue<Node> maxHeap = new PriorityQueue<>(new Comparator<Node>(){
@Override
public int compare(Node a, Node b) {
return b.cnt - a.cnt;
}
});
for (Character c : charToCnt.keySet()) {
int cnt = charToCnt.get(c);
maxHeap.offer(new Node(c, cnt));
}
StringBuilder sb = new StringBuilder();
char prev = '#';
while (!maxHeap.isEmpty()) {
Node firstCandidate = maxHeap.poll();
if (prev != '#') {
if(firstCandidate.val != prev) {
sb.append(firstCandidate.val);
prev = firstCandidate.val;
firstCandidate.cnt--;
if (firstCandidate.cnt > 0) {
maxHeap.offer(firstCandidate);
}
} else if (!maxHeap.isEmpty() && maxHeap.peek().val != prev) {
Node secondCandidate = maxHeap.poll();
sb.append(secondCandidate.val);
prev = secondCandidate.val;
secondCandidate.cnt--;
if (secondCandidate.cnt > 0) {
maxHeap.offer(secondCandidate);
}
maxHeap.offer(firstCandidate);
} else {
return "";
}
} else {
sb.append(firstCandidate.val);
prev = firstCandidate.val;
firstCandidate.cnt--;
if (firstCandidate.cnt > 0) {
maxHeap.offer(firstCandidate);
}
}
}
return sb.toString();
}
}
Task Scheduler
好题!
先用一个freqMap存charToCnt
然后再用一个maxHeap来存map.Entry
注意while循环里不能pop完就直接push, 要避免下一次pop出来是重复的task
所以要先pop出所有的task,存在list里
再update task.value(), 再push from list to heap
class Solution {
/*
map, charToCnt
minHeap<Map.Entry> sort by cnt, descending
int counter = n;
while(count-- > 0) {
//pop from heap
//不能pop完就直接push, 要避免下一次pop出来是重复的task
//所以要先pop出所有的task,存在list里
//再update task.value(), 再push from list to heap
}
*/
public int leastInterval(char[] tasks, int n) {
Map<Character, Integer> charToCnt = new HashMap<>();
for (char task : tasks) {
charToCnt.put(task, charToCnt.getOrDefault(task, 0) + 1);
}
PriorityQueue<Map.Entry<Character, Integer>> maxHeap = new PriorityQueue<>((a,b) ->(b.getValue() - a.getValue()));
for (Map.Entry<Character, Integer> entry : charToCnt.entrySet()) {
maxHeap.offer(entry);
}
int cnt = 0;
while (!maxHeap.isEmpty()) {
int interval = n + 1; //注意不是n
//先pop出所有的task,存在list里
List<Map.Entry<Character, Integer>> list = new ArrayList<>();
while (interval > 0 && !maxHeap.isEmpty()) {
Map.Entry<Character, Integer> entry = maxHeap.poll();
list.add(entry);
interval--;
cnt++;
}
//update task.value(), 再push from list to heap
for (Map.Entry<Character, Integer> entry : list) {
entry.setValue(entry.getValue() - 1);
if (entry.getValue() > 0) {
maxHeap.offer(entry);
}
}
if (!maxHeap.isEmpty()) {
cnt += interval;
}
}
return cnt;
}
}
High Five
TreeMap + minHeap
public int[][] highFive(int[][] items) {
//treeMap + minHeap
Map<Integer, PriorityQueue<Integer>> map = new TreeMap<>();
for (int i = 0; i < items.length; i++) {
int id = items[i][0];
if (!map.containsKey(id)) {
map.put(id, new PriorityQueue<>());
}
PriorityQueue<Integer> scores = map.get(id);
scores.offer(items[i][1]);
while (scores.size() > 5) {
scores.poll();
}
}
int[][] res = new int[map.size()][2];
int idx = 0;
for (int key : map.keySet()) {
PriorityQueue<Integer> scores = map.get(key);
int sum = 0;
while (!scores.isEmpty()) {
sum += scores.poll();
}
res[idx][0] = key;
res[idx][1] = sum / 5;
idx++;
}
return res;
}
Last updated
Was this helpful?