解题思路
用栈模拟单车道(出口在栈顶),用双端队列模拟入口外等待队列,再用集合维护车号是否已在车道/队列中。另用历史栈记录每次成功的 arrive / admit / depart,以支持 undo。
- arrive:未满则压栈,否则入队尾;重复车号失败
- admit:队首出队并压栈(车道须有空位)
- depart:弹出挡路车辆到临时栈,放行目标车后再压回;返回挪开数量
- undo:按历史逆操作;失败则把记录压回历史(与题面约定一致)
题目内容
小区有一条只能从一侧进出的单车道停车位,容量为 capacity。车道用栈管理:后进的车挡在出口一侧,必须先让挡路的车暂时让开,才能让里面的车离开。入口外还有一条等待队列(FIFO):车道满时新来的车只能去排队;车道有空位时可把队首车辆放进车道。
系统还要支持撤销最近一次成功的 arrive / admit / depart(用历史栈记录)。
请实现类 ParkingLane:
- ParkingLane(capacity):初始化空车道与空等待队列,capacity≥1。返回 null。
- arrive(carId):来车 carId
- 若 carId 已在车道或等待队列中,返回 false
- 若车道未满,把车压入车道栈(成为新的出口侧顶车),返回 true
- 若车道已满,把车加入等待队列尾,返回 true
- admit():尝试把等待队列队首放进车道
- 若队列为空,或车道已满,返回 false
- 否则出队并压入车道栈,返回 true
- depart(carId):让车道中的 carId 离开
- 若该车不在车道中,返回 −1
- 否则:不断把出口侧顶车弹出到临时栈,直到 carId 位于栈顶;弹出并放行 carId;再把临时栈中的车按弹出顺序压回车道(保持相对次序)。返回值是「为放行而暂时挪开的车辆数」(不含 carId 自己)
- undo():撤销最近一次成功的 arrive / admit / depart
- 若没有可撤销记录,返回 false
- 撤销规则:
- 撤销 arrive:若当时进了车道,则车道栈顶必须是该车并弹出;若当时进了等待队列,则从队列中删除该 carId(该车应仍在队列中)
- 撤销 admit:车道栈顶必须是该车,弹出后插入等待队列队首
- 撤销 depart:把该车重新压回车道栈顶(视为它回到出口侧);不恢复「当时临时挪开」的中间过程(约定如此)
- 成功撤销返回 true
- front():返回车道出口侧顶车的 carId;车道空返回 −1
- waiting():返回等待队列长度
- size():返回车道内车辆数
说明:
- 同一 carId 全局唯一占用(车道或等待队列)
- depart 只作用于车道,不能直接让等待队列中的车离开
- 只有返回成功 / depart 返回非 −1 的操作才入撤销历史
输入描述
每行一次调用,首行必须是 ParkingLane(capacity)。累计调用不超过 10000 次。
约束:
- 1≤capacity≤500
- 1≤carId≤1000000000
输出描述
每次调用一行:
- 构造返回 null
- arrive / admit / undo 返回 true / false
- depart / front / waiting / size 返回整数
样例1
输入:
ParkingLane(2)
arrive(1)
arrive(2)
arrive(3)
waiting()
size()
front()
depart(1)
front()
waiting()
admit()
front()
size()
输出:
null
true
true
true
1
2
2
1
2
1
true
3
2
说明:
- 车 1、2 进车道(栈顶为 2),3 去等待
- depart(1):先挪开 2(计 1),放行 1,再压回 2;栈顶仍为 2
- admit() 把 3 放进车道,栈顶变为 3
样例2
输入:
ParkingLane(1)
arrive(10)
arrive(20)
depart(10)
undo()
front()
waiting()
输出:
null
true
true
0
true
10
1
说明:
- 车道容量 1,20 只能去等待队列
- depart(10) 挪开数为 0;undo 后 10 回到栈顶,等待队列仍为 1
样例3
输入:
ParkingLane(3)
arrive(5)
depart(6)
arrive(5)
undo()
size()
waiting()
输出:
null
true
-1
false
true
0
0
说明:不存在的车 depart 返回 −1;重复 arrive(5) 失败;undo 撤销第一次 arrive。