Skip to content
On this page

432. 全 O(1) 的数据结构

原题链接:LeetCode 432. 全 O(1) 的数据结构

题目描述

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

实现 AllOne 类:

- `AllOne()` 初始化数据结构的对象。

- `inc(String key)` 字符串 `key` 的计数增加 `1` 。如果数据结构中尚不存在 `key` ,那么插入计数为 `1` 的 `key` 。

- `dec(String key)` 字符串 `key` 的计数减少 `1` 。如果 `key` 的计数在减少后为 `0` ,那么需要将这个 `key` 从数据结构中删除。测试用例保证:在减少计数前,`key` 存在于数据结构中。

- `getMaxKey()` 返回任意一个计数最大的字符串。如果没有元素存在,返回一个空字符串 `""` 。

- `getMinKey()` 返回任意一个计数最小的字符串。如果没有元素存在,返回一个空字符串 `""` 。

**注意:**每个函数都应当满足 O(1) 平均时间复杂度。

示例:

输入 ["AllOne", "inc", "inc", "getMaxKey", "getMinKey", "inc", "getMaxKey", "getMinKey"] [[], ["hello"], ["hello"], [], [], ["leet"], [], []] 输出 [null, null, null, "hello", "hello", null, "hello", "leet"]

解释 AllOne allOne = new AllOne(); allOne.inc("hello"); allOne.inc("hello"); allOne.getMaxKey(); // 返回 "hello" allOne.getMinKey(); // 返回 "hello" allOne.inc("leet"); allOne.getMaxKey(); // 返回 "hello" allOne.getMinKey(); // 返回 "leet"

提示:

- `1 <= key.length <= 10`

- `key` 由小写英文字母组成

- 测试用例保证:在每次调用 `dec` 时,数据结构中总存在 `key`

最多调用 `inc`、`dec`、`getMaxKey` 和 `getMinKey` 方法 5 * 104 次

难度: Hard


题解代码

javascript
var AllOne = function() {
  this.hash = {}
  this.head = new ListNode()
  this.tail = new ListNode()
  this.head.next = this.tail
  this.tail.prev = this.head
};

/** 
* @param {string} key
* @return {void}
*/
AllOne.prototype.inc = function(key) {
  if (key in this.hash) {
     this.hash[key].set.delete(key)
     const oldNode = this.hash[key]
     const isEmpty = this.hash[key].set.size === 0
     const cnt = this.hash[key].cnt
     if (cnt + 1 === this.hash[key].prev.cnt) {
         this.hash[key].prev.set.add(key)
         this.hash[key] = this.hash[key].prev
     } else {
         const node = new ListNode(cnt + 1)
         node.set.add(key)
         node.prev = this.hash[key].prev
         this.hash[key].prev.next = node
         node.next = this.hash[key]
         this.hash[key].prev = node
         this.hash[key] = node
     }
     if (isEmpty) {
         oldNode.prev.next =  oldNode.next
         oldNode.next.prev = oldNode.prev
     }
  } else {
      if (this.tail.prev.cnt === 1) {
          this.tail.prev.set.add(key)
          this.hash[key] = this.tail.prev
      } else {
          const node = new ListNode(1)
          node.set.add(key)
          this.tail.prev.next = node
          node.prev = this.tail.prev
          node.next = this.tail
          this.tail.prev = node
          this.hash[key] = node
      }
  }
};

/** 
* @param {string} key
* @return {void}
*/
AllOne.prototype.dec = function(key) {
  this.hash[key].set.delete(key)
  const oldNode = this.hash[key]
  const isEmpty = this.hash[key].set.size === 0
  const cnt = this.hash[key].cnt
  if (cnt - 1 === this.hash[key].next.cnt) {
      this.hash[key].next.set.add(key)
      this.hash[key] = this.hash[key].next
  } else if (cnt - 1 > 0) {
      const node = new ListNode(cnt - 1)
      node.set.add(key)
      node.next = this.hash[key].next
      this.hash[key].next.prev = node
      this.hash[key].next = node
      node.prev = this.hash[key]
      this.hash[key] = node
  } else if (cnt === 1) {
      delete this.hash[key]
  }
  if (isEmpty) {
      oldNode.prev.next =  oldNode.next
      oldNode.next.prev = oldNode.prev
  }
};

/**
* @return {string}
*/
AllOne.prototype.getMaxKey = function() {
  return [...this.head.next.set.keys()][0] || ''
};

/**
* @return {string}
*/
AllOne.prototype.getMinKey = function() {
  return [...this.tail.prev.set.keys()][0]|| ''
};

function ListNode (cnt) {
  this.cnt = cnt
  this.prev = null
  this.next = null
  this.set = new Set()
}

/**
 * Your AllOne object will be instantiated and called as such:
 * var obj = new AllOne()
 * obj.inc(key)
 * obj.dec(key)
 * var param_3 = obj.getMaxKey()
 * var param_4 = obj.getMinKey()
 */

技术文档集合