这是一张「动态优先级队列」:每首曲子最多在等候表里出现一次,但热度会被 boost 改掉,也可能被 cancel 撤走。用哈希表记下 当前真实热度,再用堆按「热度高优先、同热度编号小优先」弹出。
关键是 懒删除:
boost 只改哈希表里的热度,再往堆里塞一条新记录,旧记录先留着。cancel 只从哈希表删掉,堆里的旧条目先不扫。nextPlay 弹出堆顶后,对照哈希表:若该编号已不在表中,或热度对不上,说明是过期条目,丢弃再弹下一条。社区练歌房用一块麦序看板给等候的曲子排队。每首曲子有编号 songId 和当前热度 heat。下一位开唱的规则是:
请实现类 MicQueue:
MicQueue():空队列。enroll(songId, heat):把曲子加入等候。若该 songId 已经在队列里,失败返回 false;否则加入并返回 true。nextPlay():弹出并返回下一位应唱的 songId。队列为空返回 -1。boost(songId, addHeat):给仍在等候的曲子增加热度(addHeat≥1)。不在队列中则返回 false,否则改热度并返回 true。cancel(songId):从队列中撤下该曲。成功 true,本来就不在队列则 false。waiting():当前仍在等候的曲子数量。boost 只影响尚未 nextPlay 的曲子。已经唱过或被 cancel 的编号可以再次 enroll(当作新点的一首)。多次加热后热度可能超过 109,请使用 64 位整数保存热度。
每行一次调用。首行必须是 MicQueue()。累计调用不超过 8000 次。
每次调用一行:
nullenroll / boost / cancel 返回 true 或 falsenextPlay / waiting 返回整数输入:
MicQueue()
enroll(3, 10)
enroll(5, 10)
enroll(3, 20)
waiting()
nextPlay()
boost(5, 5)
enroll(8, 20)
nextPlay()
nextPlay()
cancel(9)
waiting()
输出:
null
true
true
false
2
3
true
true
8
5
false
0
说明:
10 时,编号更小的 3 先唱enroll(3,20) 失败,因为 3 还在队列里boost(5,5) 后 5 热度为 15;再加入热度 20 的 8,下一位是 8 然后是 5输入:
MicQueue()
nextPlay()
boost(1, 1)
cancel(1)
enroll(2, 1)
cancel(2)
waiting()
enroll(2, 3)
nextPlay()
输出:
null
-1
false
false
true
true
0
true
2
说明:空队列上的弹出、加热、撤销都失败;撤掉后再 enroll 同一编号是允许的。
输入:
MicQueue()
enroll(9, 1)
enroll(4, 100)
boost(9, 50)
nextPlay()
waiting()
输出:
null
true
true
true
4
1
说明:4 热度 100 仍高于被加热到 51 的 9,所以先唱 4。
Scan the QR code below with WeChat to sign in
First-time scan will create your account automatically
请使用微信扫描下方二维码完成注册