1. 程式人生 > 其它 >432. 全 O(1) 的資料結構

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();
 */