LeetCode 第432题 全O(1)的数据结构

这个和146题 LRU缓存的思路有点类似
在这里插入图片描述
纯自己想+写。改了十来次。最后结果接近双百
双向链表+哈希map

双向链表预留一个head和tail。
Solution类里有一个min变量来表示当前的出现次数最小值,max变量来表示当前的出现次数的最大值。min和max很重要,因为影响到出现次数最多和出现次数最少的字符串的有序性(head的后一个一定是出现次数最多的,tail的前一个一定是出现次数最少的,这个是核心思想)
如果增加一个新字符串,要进行判断,map里面如果没有这个字符串,就直接把这个字符串加到双向链表的尾部。如果map里面有这个字符串,就需要判断一下,字符串出现的次数与当前的最大次数和最小次数,如果出现次数大于当前最大次数max的值,则更新最大次数,如果字符串出现的次数比当前最小次数min的值要大,就要更新最小次数。
要注意的是,在增加的时候,只有当前这个字符串是min变量的时候,才需要去更新min的值,因为他可能有一个或者多个与min的值相等的Node节点,在这个字符串是min变量的时候,这个字符串的计数已经增加1了,就不会是min变量了,要从tail开始向前遍历,重新寻找一个min变量。如果当前这个字符串不是min变量,随便增加,不会影响min变量的意义,min变量还是表示出现次数最少的那个字符串。

减少一个字符串的时候同理。
只有当前这个字符串是max变量的时候,才需要去更新max的值,要从head开始向后遍历,重新寻找一个max变量。

查询字符串的时候,如果是查询出现次数最多的字符串,就返回head.next的值;如果是查询出现次数最少的字符串,就返回tail.pre的值。 因为在增加和减少一个字符串的时候,已经保证出现次数最多和出现次数最少的字符串的有序性

class AllOne {

DoubleLinkedList doubleLinkedList;
    Map<String, Node> map;
    Node min = new Node(null, Integer.MAX_VALUE);
    Node max = new Node(null, 0);

    public AllOne() {
        doubleLinkedList = new DoubleLinkedList();
        map = new HashMap<String, Node>();
    }

    public void inc(String key) {
        if(!map.containsKey(key)) {
            Node node = new Node(key, 1);
            doubleLinkedList.addNodeLast(node);
            min = node;
            map.put(key, node);
        }else {
            Node node = map.get(key);
            node.times++;
            if(node != max && node.times > max.times) {
                max = node;
                doubleLinkedList.delNode(node);
                doubleLinkedList.addNodeFirst(node);
            }
            if(node == min){
                Node temp = doubleLinkedList.tail;
                doubleLinkedList.delNode(min);
                while(temp.pre != doubleLinkedList.head && temp.pre.times < node.times){
                    temp = temp.pre;
                }
                doubleLinkedList.addNodeBeforeNode(temp, node);
                min = doubleLinkedList.tail.pre;
            }
        }
    }

    public void dec(String key) {
        Node node = map.get(key);
        node.times--;
        if(node.times == 0) {
            map.remove(key);
            doubleLinkedList.delNode(node);
            if(min == node){
                min = doubleLinkedList.tail.pre;
            }
            return;
        }
        if(node != min && node.times < min.times) {
            min = node;
            doubleLinkedList.delNode(node);
            doubleLinkedList.addNodeLast(node);
        }
        if(node == max){
            doubleLinkedList.delNode(node);
            Node temp = doubleLinkedList.head;
            while(temp.next.times > node.times){
                temp = temp.next;
            }
            doubleLinkedList.addNodeAfterNode(temp, node);
            max = doubleLinkedList.head.next;
        }
    }

    public String getMaxKey() {
        if(map.isEmpty()) {
            return "";
        }
        return doubleLinkedList.head.next.str;
    }

    public String getMinKey() {
        if(map.isEmpty()) {
            return "";
        }
        return doubleLinkedList.tail.pre.str;
    }
}
class DoubleLinkedList{
    Node head;
    Node tail;
    public DoubleLinkedList() {
        head = new Node(null, -1);
        tail = new Node(null, -1);
        head.next = tail;
        tail.pre = head;
    }

    public void addNodeFirst(Node node) {
        Node tempNode = head.next;
        head.next = node;
        node.pre = head;
        node.next = tempNode;
        tempNode.pre = node;
    }

    public void addNodeLast(Node node) {
        Node tempNode = tail.pre;
        tempNode.next = node;
        node.pre = tempNode;
        node.next = tail;
        tail.pre = node;
    }

    public void delNode(Node node) {
        Node before = node.pre;
        Node after = node.next;
        before.next = after;
        after.pre = before;
    }

    public void addNodeAfterNode(Node before, Node node){
        Node temp = before.next;
        before.next = node;
        node.pre = before;
        node.next = temp;
        temp.pre = node;
    }

    public void addNodeBeforeNode(Node after, Node node){
        Node temp = after.pre;
        temp.next = node;
        node.pre = temp;
        node.next = after;
        after.pre = node;
    }
}
class Node{
    String str;
    int times;
    Node pre;
    Node next;
    
    public Node(String str, int times) {
        this.str = str;
        this.times = times;
    }
}

结果
在这里插入图片描述

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值