Skip to content

Commit 8d108bb

Browse files
committed
设计: o1数据结构
Change-Id: I47ea35e6a5158e8c519776fd1d143de5b789fae0
1 parent 86d2ab4 commit 8d108bb

File tree

1 file changed

+194
-0
lines changed

1 file changed

+194
-0
lines changed
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
/*
2+
* @lc app=leetcode.cn id=432 lang=golang
3+
*
4+
* [432] 全 O(1) 的数据结构
5+
*
6+
* https://leetcode-cn.com/problems/all-oone-data-structure/description/
7+
*
8+
* algorithms
9+
* Hard (35.21%)
10+
* Likes: 25
11+
* Dislikes: 0
12+
* Total Accepted: 1.8K
13+
* Total Submissions: 5.1K
14+
* Testcase Example: '["AllOne","getMaxKey","getMinKey"]\n[[],[],[]]'
15+
*
16+
* 实现一个数据结构支持以下操作:
17+
*
18+
*
19+
* Inc(key) - 插入一个新的值为 1 的 key。或者使一个存在的 key 增加一,保证 key 不为空字符串。
20+
* Dec(key) - 如果这个 key 的值是 1,那么把他从数据结构中移除掉。否者使一个存在的 key 值减一。如果这个 key
21+
* 不存在,这个函数不做任何事情。key 保证不为空字符串。
22+
* GetMaxKey() - 返回 key 中值最大的任意一个。如果没有元素存在,返回一个空字符串""。
23+
* GetMinKey() - 返回 key 中值最小的任意一个。如果没有元素存在,返回一个空字符串""。
24+
*
25+
*
26+
* 挑战:以 O(1) 的时间复杂度实现所有操作。
27+
*
28+
*/
29+
30+
/*
31+
* 这个题目与155最小栈那题有点类似,但是有点不同的是每次加减1,分析一下:
32+
* 1. 必然需要一个hash结构,key输入的key,value中除数值外,一般可以带上一个指针指向其他数据结构的节点
33+
* 2. 需要保存最大最小值,注意这不是一个值,而是动态变化的一系列值,某个最大值变小之后要将次大的推上来,
34+
* 那么可选数组、链表等各种结构,hash的值指向这个节点,帮助快速定位
35+
* 3. 另外一个点是加减1这个操作,加减1之后元素可能前移可能后移,移动的时候都是跨过相等的一批值,
36+
* 如果将相同值的元素放在同一个节点上,每个节点是一个层的概念,那么移动的话只需要移动到前后层即可。
37+
* 这时候引入一个新问题,就是如何快速定位到目标点上,想当然就是hash的value中保存目标点的指针,
38+
* 另外同一层内没有移动操作,只有O(1)的查找,所以每层只需要一个hash保存即可
39+
*/
40+
41+
// @lc code=start
42+
import (
43+
"container/list"
44+
)
45+
46+
type Node struct {
47+
Key string
48+
Value int
49+
Level *Level
50+
}
51+
type Level struct {
52+
Value int
53+
Nodes map[string]bool
54+
Element *list.Element // 快速定位到链表节点,用以查找前后节点
55+
}
56+
57+
type AllOne struct {
58+
Data map[string]*Node
59+
Rank *list.List
60+
}
61+
62+
/** Initialize your data structure here. */
63+
func Constructor() AllOne {
64+
return AllOne{
65+
Data: map[string]*Node{},
66+
Rank: list.New(),
67+
}
68+
}
69+
70+
/** Inserts a new key <Key> with value 1. Or increments an existing key by 1. */
71+
func (this *AllOne) Inc(key string) {
72+
node, ok := this.Data[key]
73+
if !ok {
74+
needInsert := false
75+
var level *Level
76+
front := this.Rank.Front()
77+
// 空或者队头value大于1都需要插入
78+
if front == nil {
79+
needInsert = true
80+
} else if level = front.Value.(*Level); level.Value > 1 {
81+
needInsert = true
82+
}
83+
if needInsert {
84+
level = &Level{Value: 1, Nodes: map[string]bool{}}
85+
el := this.Rank.PushFront(level)
86+
level.Element = el
87+
}
88+
level.Nodes[key] = true
89+
node := &Node{Key: key, Value: 1, Level: level}
90+
this.Data[key] = node
91+
return
92+
}
93+
node.Value++
94+
originLevel := node.Level
95+
needInsert := false
96+
var nextLevel *Level
97+
nextLevelElement := originLevel.Element.Next()
98+
// 队尾或者下一个的value不是目标值,需要插入新节点
99+
if nextLevelElement == nil {
100+
needInsert = true
101+
} else if nextLevel = nextLevelElement.Value.(*Level); nextLevel.Value > node.Value {
102+
needInsert = true
103+
}
104+
if needInsert {
105+
nextLevel = &Level{Value: node.Value, Nodes: map[string]bool{}}
106+
el := this.Rank.InsertAfter(nextLevel, originLevel.Element)
107+
nextLevel.Element = el
108+
}
109+
110+
// 设置到新level
111+
nextLevel.Nodes[node.Key] = true
112+
node.Level = nextLevel
113+
// 清理原level
114+
delete(originLevel.Nodes, node.Key)
115+
if len(originLevel.Nodes) <= 0 {
116+
this.Rank.Remove(originLevel.Element)
117+
}
118+
}
119+
120+
/** Decrements an existing key by 1. If Key's value is 1, remove it from the data structure. */
121+
func (this *AllOne) Dec(key string) {
122+
node, ok := this.Data[key]
123+
if !ok {
124+
return
125+
}
126+
node.Value--
127+
if node.Value <= 0 { // 删除节点
128+
delete(this.Data, key)
129+
delete(node.Level.Nodes, key)
130+
if len(node.Level.Nodes) <= 0 {
131+
this.Rank.Remove(node.Level.Element)
132+
}
133+
return
134+
}
135+
originLevel := node.Level
136+
prevLevelElement := originLevel.Element.Prev()
137+
138+
needInsert := false
139+
var prevLevel *Level
140+
if prevLevelElement == nil {
141+
needInsert = true
142+
} else if prevLevel = prevLevelElement.Value.(*Level); prevLevel.Value < node.Value {
143+
needInsert = true
144+
}
145+
if needInsert {
146+
prevLevel = &Level{Value: node.Value, Nodes: map[string]bool{}}
147+
el := this.Rank.InsertBefore(prevLevel, originLevel.Element)
148+
prevLevel.Element = el
149+
}
150+
// 设置到新level
151+
prevLevel.Nodes[node.Key] = true
152+
node.Level = prevLevel
153+
// 清理原level
154+
delete(originLevel.Nodes, node.Key)
155+
if len(originLevel.Nodes) <= 0 {
156+
this.Rank.Remove(originLevel.Element)
157+
}
158+
}
159+
160+
/** Returns one of the keys with maximal value. */
161+
func (this *AllOne) GetMaxKey() string {
162+
maxLevelElement := this.Rank.Back()
163+
if maxLevelElement == nil {
164+
return ""
165+
}
166+
maxLevel := maxLevelElement.Value.(*Level)
167+
for k := range maxLevel.Nodes {
168+
return k
169+
}
170+
return ""
171+
}
172+
173+
/** Returns one of the keys with Minimal value. */
174+
func (this *AllOne) GetMinKey() string {
175+
minLevelElement := this.Rank.Front()
176+
if minLevelElement == nil {
177+
return ""
178+
}
179+
minLevel := minLevelElement.Value.(*Level)
180+
for k := range minLevel.Nodes {
181+
return k
182+
}
183+
return ""
184+
}
185+
186+
/**
187+
* Your AllOne object will be instantiated and called as such:
188+
* obj := Constructor();
189+
* obj.Inc(key);
190+
* obj.Dec(key);
191+
* param_3 := obj.GetMaxKey();
192+
* param_4 := obj.GetMinKey();
193+
*/
194+
// @lc code=end

0 commit comments

Comments
 (0)