Skip to content

Commit ef8f2d0

Browse files
authored
feat: add solutions for lc No.3815 (#4979)
1 parent 0f01f16 commit ef8f2d0

5 files changed

Lines changed: 454 additions & 8 deletions

File tree

solution/3800-3899/3815.Design Auction System/README.md

Lines changed: 155 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,26 +73,177 @@ auctionSystem.getHighestBidder(3); // 返回 -1,因为商品 3 没有任何出
7373

7474
<!-- solution:start -->
7575

76-
### 方法一
76+
### 方法一:哈希表 + 有序集合
77+
78+
我们定义两个哈希表,其中 $\textit{items}$ 用于存储每个商品的所有出价信息,即 $\textit{items}[\textit{itemId}]$ 存储一个有序集合,集合中的每个元素为一个二元组 $(\textit{bidAmount}, \textit{userId})$,表示某个用户对该商品的出价金额。由于我们需要快速获取出价最高的用户,因此该有序集合需要按照出价金额从小到大排序,如果出价金额相同,则按照用户 ID 从小到大排序;另一个哈希表 $\textit{users}$ 用于存储每个用户对各个商品的出价信息,即 $\textit{users}[\textit{userId}][\textit{itemId}]$ 存储该用户对该商品的出价金额。
79+
80+
对于 `addBid(userId, itemId, bidAmount)` 操作,我们首先检查该用户是否已经对该商品出过价,如果是,则调用 `removeBid(userId, itemId)` 方法移除原有出价;然后将新的出价信息添加到 $\textit{users}$ 和 $\textit{items}$ 中。
81+
82+
对于 `updateBid(userId, itemId, newAmount)` 操作,我们首先从 $\textit{users}$ 中获取该用户对该商品的原有出价金额,然后在 $\textit{items}$ 中移除对应的二元组 $(\textit{oldAmount}, \textit{userId})$,再将新的出价信息添加到 $\textit{items}$ 中,并更新 $\textit{users}$ 中的出价金额。
83+
84+
对于 `removeBid(userId, itemId)` 操作,我们首先从 $\textit{users}$ 中获取该用户对该商品的原有出价金额,然后在 $\textit{items}$ 中移除对应的二元组 $(\textit{oldAmount}, \textit{userId})$,最后从 $\textit{users}$ 中删除该用户对该商品的出价信息。
85+
86+
对于 `getHighestBidder(itemId)` 操作,我们首先检查 $\textit{items}[\textit{itemId}]$ 是否为空,如果为空则返回 -1;否则返回该有序集合中最后一个元素的用户 ID,即出价最高的用户。
87+
88+
时间复杂度方面,每次操作的时间复杂度均为 $O(\log m)$,其中 $m$ 为当前商品的出价数量。空间复杂度为 $O(n)$,其中 $n$ 为所有出价的总数量。
7789

7890
<!-- tabs:start -->
7991

8092
#### Python3
8193

8294
```python
83-
95+
class AuctionSystem:
96+
97+
def __init__(self):
98+
self.items = defaultdict(SortedList)
99+
self.users = {}
100+
101+
def addBid(self, userId: int, itemId: int, bidAmount: int) -> None:
102+
if userId not in self.users:
103+
self.users[userId] = {}
104+
if itemId in self.users[userId]:
105+
self.removeBid(userId, itemId)
106+
self.users[userId][itemId] = bidAmount
107+
self.items[itemId].add((bidAmount, userId))
108+
109+
def updateBid(self, userId: int, itemId: int, newAmount: int) -> None:
110+
oldAmount = self.users[userId][itemId]
111+
self.items[itemId].remove((oldAmount, userId))
112+
self.items[itemId].add((newAmount, userId))
113+
self.users[userId][itemId] = newAmount
114+
115+
def removeBid(self, userId: int, itemId: int) -> None:
116+
oldAmount = self.users[userId][itemId]
117+
self.items[itemId].remove((oldAmount, userId))
118+
self.users[userId].pop(itemId)
119+
120+
def getHighestBidder(self, itemId: int) -> int:
121+
ls = self.items[itemId]
122+
return -1 if not ls else ls[-1][1]
123+
124+
125+
# Your AuctionSystem object will be instantiated and called as such:
126+
# obj = AuctionSystem()
127+
# obj.addBid(userId,itemId,bidAmount)
128+
# obj.updateBid(userId,itemId,newAmount)
129+
# obj.removeBid(userId,itemId)
130+
# param_4 = obj.getHighestBidder(itemId)
84131
```
85132

86133
#### Java
87134

88135
```java
89-
136+
class AuctionSystem {
137+
private final Map<Integer, TreeSet<int[]>> items = new HashMap<>();
138+
private final Map<Integer, Map<Integer, Integer>> users = new HashMap<>();
139+
140+
public AuctionSystem() {
141+
}
142+
143+
public void addBid(int userId, int itemId, int bidAmount) {
144+
users.computeIfAbsent(userId, k -> new HashMap<>());
145+
146+
if (users.get(userId).containsKey(itemId)) {
147+
removeBid(userId, itemId);
148+
}
149+
150+
users.get(userId).put(itemId, bidAmount);
151+
152+
items.computeIfAbsent(itemId, k -> new TreeSet<>(
153+
(a, b) -> a[0] != b[0] ? Integer.compare(a[0], b[0]) : Integer.compare(a[1], b[1])
154+
));
155+
156+
items.get(itemId).add(new int[]{bidAmount, userId});
157+
}
158+
159+
public void updateBid(int userId, int itemId, int newAmount) {
160+
int oldAmount = users.get(userId).get(itemId);
161+
TreeSet<int[]> set = items.get(itemId);
162+
163+
set.remove(new int[]{oldAmount, userId});
164+
set.add(new int[]{newAmount, userId});
165+
166+
users.get(userId).put(itemId, newAmount);
167+
}
168+
169+
public void removeBid(int userId, int itemId) {
170+
int oldAmount = users.get(userId).get(itemId);
171+
TreeSet<int[]> set = items.get(itemId);
172+
173+
set.remove(new int[]{oldAmount, userId});
174+
users.get(userId).remove(itemId);
175+
}
176+
177+
public int getHighestBidder(int itemId) {
178+
TreeSet<int[]> set = items.get(itemId);
179+
if (set == null || set.isEmpty()) {
180+
return -1;
181+
}
182+
return set.last()[1];
183+
}
184+
}
185+
186+
/**
187+
* Your AuctionSystem object will be instantiated and called as such:
188+
* AuctionSystem obj = new AuctionSystem();
189+
* obj.addBid(userId,itemId,bidAmount);
190+
* obj.updateBid(userId,itemId,newAmount);
191+
* obj.removeBid(userId,itemId);
192+
* int param_4 = obj.getHighestBidder(itemId);
193+
*/
90194
```
91195

92196
#### C++
93197

94198
```cpp
95-
199+
class AuctionSystem {
200+
unordered_map<int, set<pair<int, int>>> items;
201+
unordered_map<int, unordered_map<int, int>> users;
202+
203+
public:
204+
AuctionSystem() {
205+
}
206+
207+
void addBid(int userId, int itemId, int bidAmount) {
208+
if (users[userId].count(itemId)) {
209+
removeBid(userId, itemId);
210+
}
211+
users[userId][itemId] = bidAmount;
212+
items[itemId].insert({bidAmount, userId});
213+
}
214+
215+
void updateBid(int userId, int itemId, int newAmount) {
216+
int oldAmount = users[userId][itemId];
217+
auto& s = items[itemId];
218+
s.erase({oldAmount, userId});
219+
s.insert({newAmount, userId});
220+
users[userId][itemId] = newAmount;
221+
}
222+
223+
void removeBid(int userId, int itemId) {
224+
int oldAmount = users[userId][itemId];
225+
auto& s = items[itemId];
226+
s.erase({oldAmount, userId});
227+
users[userId].erase(itemId);
228+
}
229+
230+
int getHighestBidder(int itemId) {
231+
auto it = items.find(itemId);
232+
if (it == items.end() || it->second.empty()) {
233+
return -1;
234+
}
235+
return it->second.rbegin()->second;
236+
}
237+
};
238+
239+
/**
240+
* Your AuctionSystem object will be instantiated and called as such:
241+
* AuctionSystem* obj = new AuctionSystem();
242+
* obj->addBid(userId,itemId,bidAmount);
243+
* obj->updateBid(userId,itemId,newAmount);
244+
* obj->removeBid(userId,itemId);
245+
* int param_4 = obj->getHighestBidder(itemId);
246+
*/
96247
```
97248

98249
#### Go

solution/3800-3899/3815.Design Auction System/README_EN.md

Lines changed: 155 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,26 +67,177 @@ auctionSystem.getHighestBidder(3); // return -1 as no bids exist for item 3</div
6767

6868
<!-- solution:start -->
6969

70-
### Solution 1
70+
### Solution 1: Hash Table + Ordered Set
71+
72+
We define two hash tables. `items` is used to store all bid information for each item, where `items[itemId]` stores an ordered set. Each element in the set is a tuple `(bidAmount, userId)`, representing a user's bid amount for that item. Since we need to quickly retrieve the user with the highest bid, this ordered set needs to be sorted by bid amount in ascending order. If bid amounts are identical, they are sorted by user ID in ascending order. The other hash table `users` is used to store the bid information of each user for each item, where `users[userId][itemId]` stores the user's bid amount for that item.
73+
74+
For the `addBid(userId, itemId, bidAmount)` operation, we first check if the user has already placed a bid on the item. If they have, we call the `removeBid(userId, itemId)` method to remove the original bid; then we add the new bid information to `users` and `items`.
75+
76+
For the `updateBid(userId, itemId, newAmount)` operation, we first retrieve the user's original bid amount for the item from `users`, then remove the corresponding tuple `(oldAmount, userId)` from `items`, add the new bid information to `items`, and update the bid amount in `users`.
77+
78+
For the `removeBid(userId, itemId)` operation, we first retrieve the user's original bid amount for the item from `users`, then remove the corresponding tuple `(oldAmount, userId)` from `items`, and finally delete the user's bid information for that item from `users`.
79+
80+
For the `getHighestBidder(itemId)` operation, we first check if `items[itemId]` is empty. If it is, we return -1; otherwise, we return the user ID of the last element in the ordered set, which corresponds to the highest bidder.
81+
82+
In terms of time complexity, each operation takes $O(\log m)$ time, where $m$ is the number of bids for the current item. The space complexity is $O(n)$, where $n$ is the total number of bids.
7183

7284
<!-- tabs:start -->
7385

7486
#### Python3
7587

7688
```python
77-
89+
class AuctionSystem:
90+
91+
def __init__(self):
92+
self.items = defaultdict(SortedList)
93+
self.users = {}
94+
95+
def addBid(self, userId: int, itemId: int, bidAmount: int) -> None:
96+
if userId not in self.users:
97+
self.users[userId] = {}
98+
if itemId in self.users[userId]:
99+
self.removeBid(userId, itemId)
100+
self.users[userId][itemId] = bidAmount
101+
self.items[itemId].add((bidAmount, userId))
102+
103+
def updateBid(self, userId: int, itemId: int, newAmount: int) -> None:
104+
oldAmount = self.users[userId][itemId]
105+
self.items[itemId].remove((oldAmount, userId))
106+
self.items[itemId].add((newAmount, userId))
107+
self.users[userId][itemId] = newAmount
108+
109+
def removeBid(self, userId: int, itemId: int) -> None:
110+
oldAmount = self.users[userId][itemId]
111+
self.items[itemId].remove((oldAmount, userId))
112+
self.users[userId].pop(itemId)
113+
114+
def getHighestBidder(self, itemId: int) -> int:
115+
ls = self.items[itemId]
116+
return -1 if not ls else ls[-1][1]
117+
118+
119+
# Your AuctionSystem object will be instantiated and called as such:
120+
# obj = AuctionSystem()
121+
# obj.addBid(userId,itemId,bidAmount)
122+
# obj.updateBid(userId,itemId,newAmount)
123+
# obj.removeBid(userId,itemId)
124+
# param_4 = obj.getHighestBidder(itemId)
78125
```
79126

80127
#### Java
81128

82129
```java
83-
130+
class AuctionSystem {
131+
private final Map<Integer, TreeSet<int[]>> items = new HashMap<>();
132+
private final Map<Integer, Map<Integer, Integer>> users = new HashMap<>();
133+
134+
public AuctionSystem() {
135+
}
136+
137+
public void addBid(int userId, int itemId, int bidAmount) {
138+
users.computeIfAbsent(userId, k -> new HashMap<>());
139+
140+
if (users.get(userId).containsKey(itemId)) {
141+
removeBid(userId, itemId);
142+
}
143+
144+
users.get(userId).put(itemId, bidAmount);
145+
146+
items.computeIfAbsent(itemId, k -> new TreeSet<>(
147+
(a, b) -> a[0] != b[0] ? Integer.compare(a[0], b[0]) : Integer.compare(a[1], b[1])
148+
));
149+
150+
items.get(itemId).add(new int[]{bidAmount, userId});
151+
}
152+
153+
public void updateBid(int userId, int itemId, int newAmount) {
154+
int oldAmount = users.get(userId).get(itemId);
155+
TreeSet<int[]> set = items.get(itemId);
156+
157+
set.remove(new int[]{oldAmount, userId});
158+
set.add(new int[]{newAmount, userId});
159+
160+
users.get(userId).put(itemId, newAmount);
161+
}
162+
163+
public void removeBid(int userId, int itemId) {
164+
int oldAmount = users.get(userId).get(itemId);
165+
TreeSet<int[]> set = items.get(itemId);
166+
167+
set.remove(new int[]{oldAmount, userId});
168+
users.get(userId).remove(itemId);
169+
}
170+
171+
public int getHighestBidder(int itemId) {
172+
TreeSet<int[]> set = items.get(itemId);
173+
if (set == null || set.isEmpty()) {
174+
return -1;
175+
}
176+
return set.last()[1];
177+
}
178+
}
179+
180+
/**
181+
* Your AuctionSystem object will be instantiated and called as such:
182+
* AuctionSystem obj = new AuctionSystem();
183+
* obj.addBid(userId,itemId,bidAmount);
184+
* obj.updateBid(userId,itemId,newAmount);
185+
* obj.removeBid(userId,itemId);
186+
* int param_4 = obj.getHighestBidder(itemId);
187+
*/
84188
```
85189

86190
#### C++
87191

88192
```cpp
89-
193+
class AuctionSystem {
194+
unordered_map<int, set<pair<int, int>>> items;
195+
unordered_map<int, unordered_map<int, int>> users;
196+
197+
public:
198+
AuctionSystem() {
199+
}
200+
201+
void addBid(int userId, int itemId, int bidAmount) {
202+
if (users[userId].count(itemId)) {
203+
removeBid(userId, itemId);
204+
}
205+
users[userId][itemId] = bidAmount;
206+
items[itemId].insert({bidAmount, userId});
207+
}
208+
209+
void updateBid(int userId, int itemId, int newAmount) {
210+
int oldAmount = users[userId][itemId];
211+
auto& s = items[itemId];
212+
s.erase({oldAmount, userId});
213+
s.insert({newAmount, userId});
214+
users[userId][itemId] = newAmount;
215+
}
216+
217+
void removeBid(int userId, int itemId) {
218+
int oldAmount = users[userId][itemId];
219+
auto& s = items[itemId];
220+
s.erase({oldAmount, userId});
221+
users[userId].erase(itemId);
222+
}
223+
224+
int getHighestBidder(int itemId) {
225+
auto it = items.find(itemId);
226+
if (it == items.end() || it->second.empty()) {
227+
return -1;
228+
}
229+
return it->second.rbegin()->second;
230+
}
231+
};
232+
233+
/**
234+
* Your AuctionSystem object will be instantiated and called as such:
235+
* AuctionSystem* obj = new AuctionSystem();
236+
* obj->addBid(userId,itemId,bidAmount);
237+
* obj->updateBid(userId,itemId,newAmount);
238+
* obj->removeBid(userId,itemId);
239+
* int param_4 = obj->getHighestBidder(itemId);
240+
*/
90241
```
91242

92243
#### Go

0 commit comments

Comments
 (0)