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

56 阅读2分钟

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

实现 AllOne 类:

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

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

算法:
方法一:hash table + 双向链表
双向链表从头到尾按字符次数递增存储,hash table存储字符在双向链表中的地址。因为inc和dec每次只对频率变化1,确实可以在O(1)时间内做到。
完全考察代码实现能力

import "math"
type AllOne struct {
    Map map[string]*Node
    LinkedListHead *Node // 双向链表头,哨兵
    LinkedListTail *Node // 双向链表尾,哨兵
}

type Node struct {
    Pre *Node
    Next *Node
    Str string
    Count int
}


func Constructor() AllOne {
    head := &Node{Count:0}
    tail := &Node{Count:math.MaxInt64}
    head.Next = tail
    tail.Pre = head
    return AllOne{
        Map: make(map[string]*Node),
        LinkedListHead: head,
        LinkedListTail: tail,
    }
}

// Map中不存在这个key,插入head之后
// 存在,node.Count++,找到链表后面node.Count更小的node,交换位置
func (this *AllOne) Inc(key string)  {
	node, ok := this.Map[key]
    if !ok {
        node = &Node{
            Str: key,
            Count: 1,
        }
		this.Map[key] = node
		this.LinkedListHead.Next.Pre = node
		node.Next = this.LinkedListHead.Next 
		node.Pre  = this.LinkedListHead
		this.LinkedListHead.Next = node
    } else {
		node.Count ++
		// pre-node-next-nNext交换node和next的位置
		for node.Count > node.Next.Count {
			next := node.Next

			next.Next.Pre = node
			node.Next = next.Next

			node.Pre.Next = next
			next.Pre = node.Pre

			node.Pre = next
			next.Next = node
		}
    }
}


func (this *AllOne) Dec(key string)  {
	node := this.Map[key]
    if node.Count == 1 {
        node.Pre.Next = node.Next
		node.Next.Pre = node.Pre
		node.Next = nil
		node.Pre = nil
		delete(this.Map, key)
    } else {
		node.Count --
		// ppre-pre-node-next交换pre和node的位置
		for node.Count < node.Pre.Count {
			pre := node.Pre

			pre.Next = node.Next
			node.Next.Pre = pre

			pre.Pre.Next = node
			node.Pre = pre.Pre

			node.Next = pre
			pre.Pre = node
		}
    }
}

// 取双向链表最后一个元素
func (this *AllOne) GetMaxKey() string {
    if this.LinkedListTail.Pre.Str != "" {
        return this.LinkedListTail.Pre.Str 
    }
    return ""
}

// 取双向链表第一个元素
func (this *AllOne) GetMinKey() string {
    if this.LinkedListHead.Next.Str != "" {
        return this.LinkedListHead.Next.Str 
    }
    return ""
}