📘 題目敘述
你要設計一個即時拍賣系統,用來管理多位使用者對多個商品的出價。
每一筆出價都包含:
userIditemIdbidAmount
請實作 AuctionSystem 類別,支援以下操作:
AuctionSystem():初始化拍賣系統addBid(int userId, int itemId, int bidAmount):- 新增一筆使用者
userId對商品itemId的出價bidAmount。 - 若同一個
userId已經對該itemId出價過,則用新的bidAmount覆蓋原本出價。
- 新增一筆使用者
updateBid(int userId, int itemId, int newAmount):- 更新
userId對itemId的既有出價為newAmount。(題目保證這筆出價存在)
- 更新
removeBid(int userId, int itemId):- 移除
userId對itemId的出價。(題目保證這筆出價存在)
- 移除
getHighestBidder(int itemId):- 回傳
itemId當前最高出價者的userId。 - 若最高出價金額相同,回傳
userId較大的那位。 - 若該商品沒有任何出價,回傳
-1。
- 回傳
條件限制
1 <= userId, itemId <= 5 * 10^41 <= bidAmount, newAmount <= 10^9addBid / updateBid / removeBid / getHighestBidder總呼叫次數最多5 * 10^4- 題目保證
updateBid與removeBid的操作一定是有效出價
🧠 解題思路(但最後TLE)
我的做法是把每個 itemId 的出價記錄分開存,並且用「兩個 vector 對齊」的方式保存出價資料:
users[itemId]:存所有對該商品出價的userIdbids[itemId]:存對應的出價金額,並且和users[itemId]用同一個索引對齊
所以對同一個 itemId 來說:
users[itemId][k]的出價金額就是bids[itemId][k]
接下來每個操作都只要在該商品的 vector 裡做線性掃描即可。
所有變數
users:二維 vector,users[itemId]存該商品所有出價者的userIdbids:二維 vector,bids[itemId]存該商品所有出價金額(索引和 users 對齊)hprice:在getHighestBidder中,當前找到的最高出價金額buser:在getHighestBidder中,對應最高出價者的userIdu:掃描某個itemId時取出的使用者 ida:掃描某個itemId時取出的出價金額i:掃描users[itemId]/bids[itemId]的索引
🪜 主要流程步驟
1. 建構子:初始化
- 我用
assign(50001, {})先建立itemId = 0~50000的容器 - 讓每個
itemId都有自己的出價列表(一開始是空的) - 之後存取
users[itemId]/bids[itemId]都不會越界
2. addBid(userId, itemId, bidAmount):新增 / 覆蓋出價
我分兩種情況處理:
情況一:同一個 userId 已經出價過
- 線性掃描
users[itemId] - 若找到
users[itemId][i] == userId- 直接覆蓋
bids[itemId][i] = bidAmount - 然後
return
- 直接覆蓋
情況二:userId 第一次對此 itemId 出價
- 把
userId加到users[itemId] - 把
bidAmount加到bids[itemId] - 兩個 vector 的索引保持對齊
3. updateBid(userId, itemId, newAmount):更新既有出價
- 題目保證這筆出價一定存在
- 所以我直接線性掃描
users[itemId] - 找到對應
userId後,把bids[itemId][i]改成newAmount,然後return
4. removeBid(userId, itemId):移除出價
- 題目保證這筆出價一定存在
- 我線性掃描
users[itemId]找到userId的位置i - 一旦找到:
users[itemId].erase(users[itemId].begin() + i)bids[itemId].erase(bids[itemId].begin() + i)
- 這樣可以確保兩個 vector 仍然索引對齊
5. getHighestBidder(itemId):找最高出價者
情況一:該商品沒有任何出價
users[itemId].empty()→ 回傳-1
情況二:有出價
- 線性掃描所有出價
(userId, bidAmount) - 若出價金額
a比目前hprice大 → 更新(hprice, buser) - 若出價金額相同
a == hprice- 題目規定要回傳
userId較大的 - 所以若
u > buser→ 更新buser
- 題目規定要回傳
最後回傳 buser。
💻 程式碼實作
class AuctionSystem {
public:
vector<vector<int>> users;
vector<vector<int>> bids;
AuctionSystem() {
users.assign(50001, {});
bids.assign(50001, {});
}
void addBid(int userId, int itemId, int bidAmount) {
for (int i = 0; i < (int)users[itemId].size(); i++) {
if (users[itemId][i] == userId) {
bids[itemId][i] = bidAmount;
return;
}
}
users[itemId].push_back(userId);
bids[itemId].push_back(bidAmount);
}
void updateBid(int userId, int itemId, int newAmount) {
for (int i = 0; i < (int)users[itemId].size(); i++) {
if (users[itemId][i] == userId) {
bids[itemId][i] = newAmount;
return;
}
}
}
void removeBid(int userId, int itemId) {
for (int i = 0; i < (int)users[itemId].size(); i++) {
if (users[itemId][i] == userId) {
users[itemId].erase(users[itemId].begin() + i);
bids[itemId].erase(bids[itemId].begin() + i);
return;
}
}
}
int getHighestBidder(int itemId) {
if (users[itemId].empty()) {
return -1;
}
int hprice = -1;
int buser = -1;
for (int i = 0; i < (int)users[itemId].size(); i++) {
int u = users[itemId][i];
int a = bids[itemId][i];
if (a > hprice || (a == hprice && u > buser)) {
hprice = a;
buser = u;
}
}
return buser;
}
};
🔗 題目連結
https://leetcode.com/problems/design-auction-system/