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();
 */
posted @   Tianyiya  阅读(56)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示