数据结构双向链表记录贴

请你设计一个用于存储字符串计数的数据结构,并能够返回计数最小和最大的字符串。

实现 AllOne 类:

AllOne() 初始化数据结构的对象。
inc(String key) 字符串 key 的计数增加 1 。如果数据结构中尚不存在 key ,那么插入计数为 1 的 key 。
dec(String key) 字符串 key 的计数减少 1 。如果 key 的计数在减少后为 0 ,那么需要将这个 key 从数据结构中删除。测试用例保证:在减少计数前,key 存在于数据结构中。
getMaxKey() 返回任意一个计数最大的字符串。如果没有元素存在,返回一个空字符串 "" 。
getMinKey() 返回任意一个计数最小的字符串。如果没有元素存在,返回一个空字符串 "" 。

来源:力扣(LeetCode)
 

class AllOne {

    // 双向链表按次数从小到大排序
    Node head, tail;
    // 哈希表保存 key->Node 的映射
    Map<String, Node> map;

    public AllOne() {
        this.head = new Node(-1);
        this.tail = new Node(10000000);
        this.head.next = this.tail;
        this.tail.prev = this.head;
        this.map = new HashMap<>();
    }

    public void inc(String key) {
        if (map.containsKey(key)) {
            // 包含key的情况下
            Node node = map.get(key);
            Node next = node.next;
            int newCount = node.count + 1;

            // 如果下一节点的数量等于新数量
            // 则key加入下一个节点
            if (next.count == newCount) {
                next.addKey(key);
                map.put(key, next);
            } else {
                // 否则新建一个Node并插入到当前节点之后
                Node newNode = new Node(key, newCount);
                node.next(newNode);
                map.put(key, newNode);
            }

            // 当前节点移除这个key
            node.removeKey(key);
        } else {
            // 不包含这个key的情况下
            // 直接看head的下一个节点的数量是不是1
            Node head = this.head;
            Node next = head.next;
            if (next.count == 1) {
                next.addKey(key);
                map.put(key, next);
            } else {
                Node newNode = new Node(key, 1);
                head.next(newNode);
                map.put(key, newNode);
            }
        }
    }

    public void dec(String key) {
        // 题目约定了一定包含这个key
        Node node = map.get(key);
        Node prev = node.prev;
        int newCount = node.count - 1;

        if (prev.count == newCount) {
            prev.addKey(key);
            map.put(key, prev);
        } else if (newCount == 0){
            map.remove(key);
        } else {
            Node newNode = new Node(key, newCount);
            node.prev(newNode);
            map.put(key, newNode);
        }

        node.removeKey(key);
    }

    public String getMaxKey() {
        if (tail.prev == head) {
            return "";
        }
        return tail.prev.keys.iterator().next();
    }

    public String getMinKey() {
        if (head.next == tail) {
            return "";
        }
        return head.next.keys.iterator().next();
    }

    static class Node {
        int count;
        Node next;
        Node prev;
        Set<String> keys;

        Node(int count) {
            this.count = count;
        }

        Node(String key, int count) {
            this.keys = new HashSet<>();
            this.keys.add(key);
            this.count = count;
        }

        void addKey(String key) {
            this.keys.add(key);
        }

        void removeKey(String key) {
            this.keys.remove(key);
            if (this.keys.isEmpty()) {
                remove();
            }
        }

        void next(Node next) {
            // 在当前节点后面插入一个节点
            Node nextnext = this.next;
            this.next = next;
            next.prev = this;
            next.next = nextnext;
            nextnext.prev = next;
        }

        void prev(Node prev) {
            // 在当前节点前面插入一个节点
            Node prevprev = this.prev;
            this.prev = prev;
            prev.next = this;
            prev.prev = prevprev;
            prevprev.next = prev;
        }

        void remove() {
            // 删除当前节点
            Node prev = this.prev;
            Node next = this.next;
            prev.next = next;
            next.prev = prev;
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值