432. 全 O(1) 的数据结构
请你设计一个用于存储字符串计数的数据结构,并能够返回计数最小和最大的字符串。
实现 AllOne 类:
AllOne() 初始化数据结构的对象。
inc(String key) 字符串 key 的计数增加 1 。如果数据结构中尚不存在 key ,那么插入计数为 1 的 key 。
dec(String key) 字符串 key 的计数减少 1 。如果 key 的计数在减少后为 0 ,那么需要将这个 key 从数据结构中删除。测试用例保证:在减少计数前,key 存在于数据结构中。
getMaxKey() 返回任意一个计数最大的字符串。如果没有元素存在,返回一个空字符串 "" 。
getMinKey() 返回任意一个计数最小的字符串。如果没有元素存在,返回一个空字符串 "" 。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/all-oone-data-structure
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
class AllOne {
private DoubleLinkedList doubleLinkedList;
private Map<String, DoubleLinkedList.Node> nodeMap;
public AllOne() {
this.doubleLinkedList = new DoubleLinkedList();
this.nodeMap = new HashMap<>();
}
public void inc(String key) {
DoubleLinkedList.Node node = nodeMap.get(key);
DoubleLinkedList.Node newNode;
/**
* 新的key
*/
if (node == null) {
/**
* 存在1的节点
*/
if (doubleLinkedList.getHead().next.val == 1) {
newNode = doubleLinkedList.getHead().next;
newNode.keys.add(key);
} else {
/**
* 不存在1的节点
*/
newNode = new DoubleLinkedList.Node(1);
newNode.keys.add(key);
doubleLinkedList.insertAfter(doubleLinkedList.getHead(), newNode);
}
} else {
/**
* 老key
*/
/**
* 从原节点删除
*/
node.keys.remove(key);
if (node.val + 1 == node.next.val) {
newNode = node.next;
newNode.keys.add(key);
nodeMap.put(key, newNode);
} else {
newNode = new DoubleLinkedList.Node(node.val + 1);
newNode.keys.add(key);
doubleLinkedList.insertAfter(node, newNode);
nodeMap.put(key, newNode);
}
if (node.keys.size() == 0) {
doubleLinkedList.remove(node);
}
}
nodeMap.put(key, newNode);
}
public void dec(String key) {
DoubleLinkedList.Node node = nodeMap.get(key);
if (node != null) {
node.keys.remove(key);
if (node.val != 1) {
if (node.prev == doubleLinkedList.getHead() || node.prev.val + 1 != node.val) {
DoubleLinkedList.Node newNode = new DoubleLinkedList.Node(node.val - 1);
newNode.keys.add(key);
doubleLinkedList.insertAfter(node.prev, newNode);
nodeMap.put(key, newNode);
} else {
DoubleLinkedList.Node newNode = node.prev;
newNode.keys.add(key);
nodeMap.put(key, newNode);
}
} else {
nodeMap.remove(key);
}
if (node.keys.size() == 0) {
doubleLinkedList.remove(node);
}
}
}
public String getMaxKey() {
if (doubleLinkedList.getHead().next == doubleLinkedList.getTail()) {
return "";
}
return doubleLinkedList.getTail().prev.keys.iterator().next();
}
public String getMinKey() {
if (doubleLinkedList.getHead().next == doubleLinkedList.getTail()) {
return "";
}
return doubleLinkedList.getHead().next.keys.iterator().next();
}
}
class DoubleLinkedList {
private Node head;
private Node tail;
public DoubleLinkedList() {
this.head = new Node(0);
this.tail = new Node(0);
head.next = tail;
tail.prev = head;
}
static class Node {
int val;
Node prev;
Node next;
Set<String> keys;
public Node(int val) {
this.val = val;
this.keys = new HashSet<>();
}
}
public void remove(Node node) {
Node prev = node.prev;
Node next = node.next;
prev.next = next;
next.prev = prev;
}
public void insertAfter(Node node, Node inserted) {
Node next = node.next;
node.next = inserted;
inserted.prev = node;
inserted.next = next;
next.prev = inserted;
}
public Node getHead() {
return head;
}
public void setHead(Node head) {
this.head = head;
}
public Node getTail() {
return tail;
}
public void setTail(Node tail) {
this.tail = tail;
}
}
/**
* Your AllOne object will be instantiated and called as such:
* AllOne obj = new AllOne();
* obj.inc(key);
* obj.dec(key);
* String param_3 = obj.getMaxKey();
* String param_4 = obj.getMinKey();
*/
心之所向,素履以往 生如逆旅,一苇以航
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理