Skip to content

Commit 76061c9

Browse files
committed
feat: add solutions to lc problem: No.0981
No.0981.Time Based Key-Value Store
1 parent fbd2ce8 commit 76061c9

File tree

6 files changed

+174
-79
lines changed

6 files changed

+174
-79
lines changed

solution/0900-0999/0981.Time Based Key-Value Store/README.md

Lines changed: 63 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,13 @@ timeMap.get("foo", 5); // 返回 "bar2"
5858

5959
<!-- 这里可写通用的实现逻辑 -->
6060

61-
嵌套哈希表实现。
61+
**方法一:哈希表 + 有序集合(或二分查找)**
62+
63+
我们可以用哈希表 $ktv$ 记录键值对,其中键为字符串 $key$,值为一个列表,列表中的每个元素为一个二元组 $(timestamp, value)$,表示键 $key$ 在时间戳 $timestamp$ 时对应的值为 $value$。
64+
65+
当我们需要查询键 $key$ 在时间戳 $timestamp$ 时对应的值时,我们可以通过二分查找的方法在 $ktv[key]$ 中找到最大的时间戳 $timestamp'$,使得 $timestamp' \leq timestamp$,然后返回对应的值即可。
66+
67+
时间复杂度方面,对于 $set$ 操作,由于哈希表的插入操作的时间复杂度为 $O(1)$,因此时间复杂度为 $O(1)$。对于 $get$ 操作,由于哈希表的查找操作的时间复杂度为 $O(1)$,而二分查找的时间复杂度为 $O(\log n)$,因此时间复杂度为 $O(\log n)$。空间复杂度为 $O(n)$,其中 $n$ 为 $set$ 操作的次数。
6268

6369
<!-- tabs:start -->
6470

@@ -68,10 +74,8 @@ timeMap.get("foo", 5); // 返回 "bar2"
6874

6975
```python
7076
class TimeMap:
77+
7178
def __init__(self):
72-
"""
73-
Initialize your data structure here.
74-
"""
7579
self.ktv = defaultdict(list)
7680

7781
def set(self, key: str, value: str, timestamp: int) -> None:
@@ -81,7 +85,6 @@ class TimeMap:
8185
if key not in self.ktv:
8286
return ''
8387
tv = self.ktv[key]
84-
# #查找第一个大于timestamp的
8588
i = bisect_right(tv, (timestamp, chr(127)))
8689
return tv[i - 1][1] if i else ''
8790

@@ -98,11 +101,10 @@ class TimeMap:
98101

99102
```java
100103
class TimeMap {
101-
private Map<String, TreeMap<Integer, String>> ktv;
104+
private Map<String, TreeMap<Integer, String>> ktv = new HashMap<>();
102105

103-
/** Initialize your data structure here. */
104106
public TimeMap() {
105-
ktv = new HashMap<>();
107+
106108
}
107109

108110
public void set(String key, String value, int timestamp) {
@@ -113,7 +115,7 @@ class TimeMap {
113115
if (!ktv.containsKey(key)) {
114116
return "";
115117
}
116-
TreeMap<Integer, String> tv = ktv.get(key);
118+
var tv = ktv.get(key);
117119
Integer t = tv.floorKey(timestamp);
118120
return t == null ? "" : tv.get(t);
119121
}
@@ -127,39 +129,73 @@ class TimeMap {
127129
*/
128130
```
129131

130-
### **Go**
132+
### **C++**
131133

132-
因为 timestamp 是一直增长的,所以可以用二分查找快速找到值
134+
```cpp
135+
class TimeMap {
136+
public:
137+
TimeMap() {
133138

134-
```go
135-
type pair struct {
136-
timestamp int
137-
value string
138-
}
139+
}
140+
141+
void set(string key, string value, int timestamp) {
142+
ktv[key].emplace_back(timestamp, value);
143+
}
144+
145+
string get(string key, int timestamp) {
146+
auto& pairs = ktv[key];
147+
pair<int, string> p = {timestamp, string({127})};
148+
auto i = upper_bound(pairs.begin(), pairs.end(), p);
149+
return i == pairs.begin() ? "" : (i - 1)->second;
150+
}
151+
152+
private:
153+
unordered_map<string, vector<pair<int, string>>> ktv;
154+
};
139155

156+
/**
157+
* Your TimeMap object will be instantiated and called as such:
158+
* TimeMap* obj = new TimeMap();
159+
* obj->set(key,value,timestamp);
160+
* string param_2 = obj->get(key,timestamp);
161+
*/
162+
```
163+
164+
### **Go**
165+
166+
```go
140167
type TimeMap struct {
141-
data map[string][]pair
168+
ktv map[string][]pair
142169
}
143170
144171
func Constructor() TimeMap {
145-
return TimeMap{data: make(map[string][]pair)}
172+
return TimeMap{map[string][]pair{}}
146173
}
147174
148-
func (m *TimeMap) Set(key string, value string, timestamp int) {
149-
m.data[key] = append(m.data[key], pair{timestamp, value})
175+
func (this *TimeMap) Set(key string, value string, timestamp int) {
176+
this.ktv[key] = append(this.ktv[key], pair{timestamp, value})
150177
}
151178
152-
func (m *TimeMap) Get(key string, timestamp int) string {
153-
pairs := m.data[key]
154-
// sort.Search return the smallest index i in [0, n) at which f(i) is true
155-
i := sort.Search(len(pairs), func(i int) bool {
156-
return pairs[i].timestamp > timestamp
157-
})
179+
func (this *TimeMap) Get(key string, timestamp int) string {
180+
pairs := this.ktv[key]
181+
i := sort.Search(len(pairs), func(i int) bool { return pairs[i].t > timestamp })
158182
if i > 0 {
159-
return pairs[i-1].value
183+
return pairs[i-1].v
160184
}
161185
return ""
162186
}
187+
188+
type pair struct {
189+
t int
190+
v string
191+
}
192+
193+
/**
194+
* Your TimeMap object will be instantiated and called as such:
195+
* obj := Constructor();
196+
* obj.Set(key,value,timestamp);
197+
* param_2 := obj.Get(key,timestamp);
198+
*/
163199
```
164200

165201
### **...**

solution/0900-0999/0981.Time Based Key-Value Store/README_EN.md

Lines changed: 58 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,8 @@ timeMap.get(&quot;foo&quot;, 5); // return &quot;bar2&quot;
5353

5454
```python
5555
class TimeMap:
56+
5657
def __init__(self):
57-
"""
58-
Initialize your data structure here.
59-
"""
6058
self.ktv = defaultdict(list)
6159

6260
def set(self, key: str, value: str, timestamp: int) -> None:
@@ -80,22 +78,21 @@ class TimeMap:
8078

8179
```java
8280
class TimeMap {
83-
private Map<String, TreeMap<Integer, String>> ktv;
81+
private Map<String, TreeMap<Integer, String>> ktv = new HashMap<>();
8482

85-
/** Initialize your data structure here. */
8683
public TimeMap() {
87-
ktv = new HashMap<>();
88-
}
8984

85+
}
86+
9087
public void set(String key, String value, int timestamp) {
9188
ktv.computeIfAbsent(key, k -> new TreeMap<>()).put(timestamp, value);
9289
}
93-
90+
9491
public String get(String key, int timestamp) {
9592
if (!ktv.containsKey(key)) {
9693
return "";
9794
}
98-
TreeMap<Integer, String> tv = ktv.get(key);
95+
var tv = ktv.get(key);
9996
Integer t = tv.floorKey(timestamp);
10097
return t == null ? "" : tv.get(t);
10198
}
@@ -109,39 +106,73 @@ class TimeMap {
109106
*/
110107
```
111108

112-
### **Go**
109+
### **C++**
113110

114-
Because timestamp is always increasing, you can use binary search to quickly find the value
111+
```cpp
112+
class TimeMap {
113+
public:
114+
TimeMap() {
115115

116-
```go
117-
type pair struct {
118-
timestamp int
119-
value string
120-
}
116+
}
117+
118+
void set(string key, string value, int timestamp) {
119+
ktv[key].emplace_back(timestamp, value);
120+
}
121+
122+
string get(string key, int timestamp) {
123+
auto& pairs = ktv[key];
124+
pair<int, string> p = {timestamp, string({127})};
125+
auto i = upper_bound(pairs.begin(), pairs.end(), p);
126+
return i == pairs.begin() ? "" : (i - 1)->second;
127+
}
128+
129+
private:
130+
unordered_map<string, vector<pair<int, string>>> ktv;
131+
};
132+
133+
/**
134+
* Your TimeMap object will be instantiated and called as such:
135+
* TimeMap* obj = new TimeMap();
136+
* obj->set(key,value,timestamp);
137+
* string param_2 = obj->get(key,timestamp);
138+
*/
139+
```
121140
141+
### **Go**
142+
143+
```go
122144
type TimeMap struct {
123-
data map[string][]pair
145+
ktv map[string][]pair
124146
}
125147
126148
func Constructor() TimeMap {
127-
return TimeMap{data: make(map[string][]pair)}
149+
return TimeMap{map[string][]pair{}}
128150
}
129151
130-
func (m *TimeMap) Set(key string, value string, timestamp int) {
131-
m.data[key] = append(m.data[key], pair{timestamp, value})
152+
func (this *TimeMap) Set(key string, value string, timestamp int) {
153+
this.ktv[key] = append(this.ktv[key], pair{timestamp, value})
132154
}
133155
134-
func (m *TimeMap) Get(key string, timestamp int) string {
135-
pairs := m.data[key]
136-
// sort.Search return the smallest index i in [0, n) at which f(i) is true
137-
i := sort.Search(len(pairs), func(i int) bool {
138-
return pairs[i].timestamp > timestamp
139-
})
156+
func (this *TimeMap) Get(key string, timestamp int) string {
157+
pairs := this.ktv[key]
158+
i := sort.Search(len(pairs), func(i int) bool { return pairs[i].t > timestamp })
140159
if i > 0 {
141-
return pairs[i-1].value
160+
return pairs[i-1].v
142161
}
143162
return ""
144163
}
164+
165+
type pair struct {
166+
t int
167+
v string
168+
}
169+
170+
/**
171+
* Your TimeMap object will be instantiated and called as such:
172+
* obj := Constructor();
173+
* obj.Set(key,value,timestamp);
174+
* param_2 := obj.Get(key,timestamp);
175+
*/
145176
```
146177

147178
### **...**
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
class TimeMap {
2+
public:
3+
TimeMap() {
4+
5+
}
6+
7+
void set(string key, string value, int timestamp) {
8+
ktv[key].emplace_back(timestamp, value);
9+
}
10+
11+
string get(string key, int timestamp) {
12+
auto& pairs = ktv[key];
13+
pair<int, string> p = {timestamp, string({127})};
14+
auto i = upper_bound(pairs.begin(), pairs.end(), p);
15+
return i == pairs.begin() ? "" : (i - 1)->second;
16+
}
17+
18+
private:
19+
unordered_map<string, vector<pair<int, string>>> ktv;
20+
};
21+
22+
/**
23+
* Your TimeMap object will be instantiated and called as such:
24+
* TimeMap* obj = new TimeMap();
25+
* obj->set(key,value,timestamp);
26+
* string param_2 = obj->get(key,timestamp);
27+
*/
Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,32 @@
1-
type pair struct {
2-
timestamp int
3-
value string
4-
}
5-
61
type TimeMap struct {
7-
data map[string][]pair
2+
ktv map[string][]pair
83
}
94

105
func Constructor() TimeMap {
11-
return TimeMap{data: make(map[string][]pair)}
6+
return TimeMap{map[string][]pair{}}
127
}
138

14-
func (m *TimeMap) Set(key string, value string, timestamp int) {
15-
m.data[key] = append(m.data[key], pair{timestamp, value})
9+
func (this *TimeMap) Set(key string, value string, timestamp int) {
10+
this.ktv[key] = append(this.ktv[key], pair{timestamp, value})
1611
}
1712

18-
func (m *TimeMap) Get(key string, timestamp int) string {
19-
pairs := m.data[key]
20-
// sort.Search return the smallest index i in [0, n) at which f(i) is true
21-
i := sort.Search(len(pairs), func(i int) bool {
22-
return pairs[i].timestamp > timestamp
23-
})
13+
func (this *TimeMap) Get(key string, timestamp int) string {
14+
pairs := this.ktv[key]
15+
i := sort.Search(len(pairs), func(i int) bool { return pairs[i].t > timestamp })
2416
if i > 0 {
25-
return pairs[i-1].value
17+
return pairs[i-1].v
2618
}
2719
return ""
2820
}
21+
22+
type pair struct {
23+
t int
24+
v string
25+
}
26+
27+
/**
28+
* Your TimeMap object will be instantiated and called as such:
29+
* obj := Constructor();
30+
* obj.Set(key,value,timestamp);
31+
* param_2 := obj.Get(key,timestamp);
32+
*/

solution/0900-0999/0981.Time Based Key-Value Store/Solution.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,19 @@
11
class TimeMap {
2-
private Map<String, TreeMap<Integer, String>> ktv;
2+
private Map<String, TreeMap<Integer, String>> ktv = new HashMap<>();
33

4-
/** Initialize your data structure here. */
54
public TimeMap() {
6-
ktv = new HashMap<>();
7-
}
85

6+
}
7+
98
public void set(String key, String value, int timestamp) {
109
ktv.computeIfAbsent(key, k -> new TreeMap<>()).put(timestamp, value);
1110
}
12-
11+
1312
public String get(String key, int timestamp) {
1413
if (!ktv.containsKey(key)) {
1514
return "";
1615
}
17-
TreeMap<Integer, String> tv = ktv.get(key);
16+
var tv = ktv.get(key);
1817
Integer t = tv.floorKey(timestamp);
1918
return t == null ? "" : tv.get(t);
2019
}

solution/0900-0999/0981.Time Based Key-Value Store/Solution.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
class TimeMap:
2+
23
def __init__(self):
3-
"""
4-
Initialize your data structure here.
5-
"""
64
self.ktv = defaultdict(list)
75

86
def set(self, key: str, value: str, timestamp: int) -> None:

0 commit comments

Comments
 (0)