// leetcode895 最大频次栈
// 其实就是每个元素多了一个频次,为了O(1)获取元素频次,有了一个value-Frequency的映射
// 其次,因为同频次下,按照栈的逻辑先进后出, 同频次需要一个栈
// 为了熟悉链表,用的单链表模拟栈,其实可以用现有的stack库
// 每个频次都需要一个栈,即同一个x在多个频次下有多个副本
// 其实也想过像LFU那样,只存储唯一的副本,但是无法保证x在多个频次下的栈的位置,需要记录
// x在每个频次下的栈中位置,这样在删除x时,无法保证O(1)操作
// 另外还需要维护当前结构的元素的最大频次,以便出栈O(1)
class FreqStack {
int maxFreq;
HashMap<Integer, Integer> valToFreq;
HashMap<Integer, LinkedStack> freqTable;
public FreqStack() {
valToFreq = new HashMap<>();
freqTable = new HashMap<>();
maxFreq = 0;
}
public void push(int val) {
ListNode node = new ListNode(val);
int freq = 0;
if (valToFreq.containsKey(val)) {
freq = valToFreq.get(val);
freq++;
}else {
freq = 1;
}
if (!freqTable.containsKey(freq))
freqTable.put(freq, new LinkedStack());
if (maxFreq < freq) // 更新栈最大频次
maxFreq = freq;
freqTable.get(freq).addNode(node);
valToFreq.put(val, freq);
}
public int pop() {
if (maxFreq == 0) // 栈中没有元素
return -1;
LinkedStack stack = freqTable.get(maxFreq);
int freq = maxFreq;
int val = stack.removeHead();
if (stack.isEmpty()){ // 最大频次只有一个元素
freqTable.remove(maxFreq);
maxFreq--;
}
if (maxFreq == 0)
valToFreq.remove(val);
else
valToFreq.put(val, freq - 1);
return val;
}
}
class ListNode {
int val;
ListNode next;
ListNode() {}
ListNode(int val) {
this.val = val;
next = null;
}
}
class LinkedStack {
private ListNode head;
public LinkedStack() {
head = new ListNode();
head.next = null;
}
public void addNode(ListNode node) {
node.next = head.next;
head.next = node;
}
public int removeHead(){
return removeNode(head.next);
}
public int removeNode(ListNode node) {
head.next = node.next;
return node.val;
}
public boolean isEmpty() {
if (head.next == null)
return true;
return false;
}
}