package com.dong.mytest.demo.other.yan;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
public class TicketSystem {
/**
* 订单状态 0-初始状态 1-预定失败 2-预定成功 3-已取消
*/
public static final Integer ORDER_STATUS_INIT = 0;
public static final Integer ORDER_STATUS_FAILED = 1;
public static final Integer ORDER_STATUS_SUCCESS = 2;
public static final Integer ORDER_STATUS_CANCEL = 3;
/**
* 座位状态 0-空位 1-已预订
*/
public static final Integer SEAT_STATUS_EMPTY = 0;
public static final Integer SEAT_STATUS_ORDERED = 1;
/**
* 舱位id map
*/
private Map<Integer, Cabin> cabinMap = new HashMap<>(16);
/**
* 订单map
*/
private Map<Integer, TicketOrder> orderMap = new HashMap<>(16);
public TicketSystem(int[] cabins) {
if (cabins == null) {
throw new RuntimeException("初始化参数错误");
}
// 初始化每个船舱的信息:id,座位列表,候补队列
for (int i = 0; i < cabins.length; i++) {
int cabinCount = cabins[i];
List<Integer> seatList = new ArrayList<>(cabinCount);
for (int j = 0; j < cabinCount; j++) {
// 0-空位 1-已被定
seatList.add(SEAT_STATUS_EMPTY);
}
Cabin cabin = new Cabin();
cabin.setCabinId(i);
cabin.setSeatList(seatList);
cabinMap.put(i, cabin);
}
}
/**
* 从cabinId舱位中预定num个座位,订单编号为id
*/
public boolean book(int id, int cabinId, int num) {
if (cabinMap.get(cabinId) == null) {
System.out.println("cabinId有误");
return false;
}
if (orderMap.containsKey(id)) {
System.out.println("订单id已存在,请确认后再试");
return false;
}
Cabin cabin = cabinMap.get(cabinId);
// 生成订单
TicketOrder order = new TicketOrder();
order.setId(id);
order.setCabinId(cabinId);
order.setNum(num);
order.setStatus(ORDER_STATUS_INIT);
orderMap.put(id, order);
// 该船舱的候补队列
List<TicketOrder> hbQueue = cabin.getHbQueue();
// 候补队列为空
if (hbQueue.isEmpty()) {
// 该船舱剩余座位列表
List<Integer> remainSeatNumList = cabin.getRemainSeatNumList();
// 有足够余票
if (remainSeatNumList.size() >= num) {
// 根据连续优先订票规则,获取座位号
List<Integer> seatNumList = checkHasContinuousSeatNum(remainSeatNumList, num);
for (Integer seatNum : seatNumList) {
// 修改座位号状态
cabin.getSeatList().set(seatNum, SEAT_STATUS_ORDERED);
}
// 记录订单预定的座位列表
order.setOrderSeatNumList(seatNumList);
order.setStatus(ORDER_STATUS_SUCCESS);
return true;
} else {
// 余票不足,该订单进入该船舱的候补队列队尾
order.setStatus(ORDER_STATUS_FAILED);
hbQueue.add(order);
return false;
}
} else {
// 候补队列非空,直接进入候补队列队尾
order.setStatus(ORDER_STATUS_FAILED);
hbQueue.add(order);
return false;
}
}
/**
* 根据连续优先订票规则,获取座位号
*/
private List<Integer> checkHasContinuousSeatNum(List<Integer> remainSeatNumList, int orderSeatCount) {
// 连续座位号列表
List<Integer> list = new ArrayList<>();
// 上一个座位号
Integer preSeatNum = null;
for (Integer seatNum : remainSeatNumList) {
// 如果当前座位号和上一个不是差1,则说明不连续,清空
if (preSeatNum != null && !seatNum.equals(preSeatNum + 1)) {
list.clear();
}
list.add(seatNum);
// 如果连续座位号达到订票数,则直接返回
if (list.size() >= orderSeatCount) {
return list;
}
preSeatNum = seatNum;
}
// 走到这里说明没有连续的号,返回最小的几个座位号
list.clear();
for (Integer seatNum : remainSeatNumList) {
if (list.size() < orderSeatCount) {
list.add(seatNum);
} else {
break;
}
}
return list;
}
/**
* 取消编号为id的订单,并及时处理候补队列订单
*/
public boolean cancel(int id) {
if (orderMap.get(id) == null) {
System.out.println("订单id不存在");
return false;
}
TicketOrder order = orderMap.get(id);
Cabin cabin = cabinMap.get(order.getCabinId());
boolean result = false;
// 如果该订单已预定成功,则成功取消订单、退票并返回true
if (ORDER_STATUS_SUCCESS.equals(order.getStatus())) {
// 回补座位
List<Integer> orderSeatNumList = order.getOrderSeatNumList();
for (Integer seatNum : orderSeatNumList) {
// 将船舱的座位状态修改为 0-空位
cabin.getSeatList().set(seatNum, SEAT_STATUS_EMPTY);
}
// 候补队列尝试继续买票
queueRetry(cabin);
result = true;
} else if (ORDER_STATUS_FAILED.equals(order.getStatus())) {
cabin.getHbQueue().removeIf(item -> item.getId() == order.getId());
// 后面的候补队列尝试继续买票
queueRetry(cabin);
result = true;
} else {
// 其他:0-初始状态 3-已取消 直接返回false
}
// 修改订单状态
order.setStatus(ORDER_STATUS_CANCEL);
order.setOrderSeatNumList(new ArrayList<>());
return result;
}
/**
* 候补队列尝试继续买票
*/
private void queueRetry(Cabin cabin) {
Iterator<TicketOrder> iterator = cabin.getHbQueue().iterator();
while (iterator.hasNext()) {
TicketOrder ticketOrder = iterator.next();
// 该船舱剩余座位列表
List<Integer> remainSeatNumList = cabin.getRemainSeatNumList();
// 没有足够的余票,直接退出
if (remainSeatNumList.size() < ticketOrder.getNum()) {
break;
}
// 有足够余票,根据连续优先订票规则,获取座位号
List<Integer> seatNumList = checkHasContinuousSeatNum(remainSeatNumList, ticketOrder.getNum());
for (Integer seatNum : seatNumList) {
// 修改座位号状态
cabin.getSeatList().set(seatNum, SEAT_STATUS_ORDERED);
}
// 记录订单预定的座位列表
ticketOrder.setOrderSeatNumList(seatNumList);
ticketOrder.setStatus(ORDER_STATUS_SUCCESS);
// 从队列中移除
iterator.remove();
}
}
public int query(int id) {
TicketOrder order = orderMap.get(id);
if (order == null || !ORDER_STATUS_SUCCESS.equals(order.getStatus())) {
return -1;
}
// 如果预定成功,则返回最小的座位号
return order.getOrderSeatNumList().get(0);
}
public static void main(String[] args) {
TicketSystem ticketSystem = new TicketSystem(new int[]{10, 1});
System.out.println(ticketSystem.book(71, 0, 2));
System.out.println(ticketSystem.book(73, 0, 10));
System.out.println(ticketSystem.book(72, 0, 2));
System.out.println(ticketSystem.query(72));
System.out.println(ticketSystem.book(74, 0, 2));
System.out.println(ticketSystem.cancel(73));
System.out.println(ticketSystem.query(74));
System.out.println(ticketSystem.query(72));
System.out.println(ticketSystem.cancel(72));
System.out.println(ticketSystem.book(75, 0, 3));
System.out.println(ticketSystem.query(75));
System.out.println(ticketSystem.cancel(75));
System.out.println(ticketSystem.book(76, 0, 2));
System.out.println(ticketSystem.book(77, 0, 2));
System.out.println(ticketSystem.cancel(76));
System.out.println(ticketSystem.book(78, 0, 3));
System.out.println(ticketSystem.query(78));
}
}
package com.dong.mytest.demo.other.yan;
import java.util.ArrayList;
import java.util.List;
public class Cabin {
/**
* 船舱编号
*/
private int cabinId;
/**
* 座位列表,list下标代表座位号,0代表空位,1代表被定了
*/
private List<Integer> seatList;
/**
* 候补队列
*/
private List<TicketOrder> hbQueue = new ArrayList<>();
/**
* 获取剩余的座位号列表
*
* @return list
*/
public List<Integer> getRemainSeatNumList() {
List<Integer> remainSeatNumList = new ArrayList<>();
for (int i = 0; i < seatList.size(); i++) {
Integer flag = seatList.get(i);
if (flag.equals(0)) {
remainSeatNumList.add(i);
}
}
return remainSeatNumList;
}
public int getCabinId() {
return cabinId;
}
public void setCabinId(int cabinId) {
this.cabinId = cabinId;
}
public List<Integer> getSeatList() {
return seatList;
}
public void setSeatList(List<Integer> seatList) {
this.seatList = seatList;
}
public List<TicketOrder> getHbQueue() {
return hbQueue;
}
public void setHbQueue(List<TicketOrder> hbQueue) {
this.hbQueue = hbQueue;
}
}
package com.dong.mytest.demo.other.yan;
import java.util.List;
public class TicketOrder {
/**
* 订单id
*/
private int id;
/**
* 预订的船舱id
*/
private int cabinId;
/**
* 预定座位数
*/
private int num;
/**
* 预定的座位编号列表
*/
private List<Integer> orderSeatNumList;
/**
* 订单状态 0-初始状态 1-预定失败 2-预定成功 3-已取消
*/
private int status;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public List<Integer> getOrderSeatNumList() {
return orderSeatNumList;
}
public void setOrderSeatNumList(List<Integer> orderSeatNumList) {
this.orderSeatNumList = orderSeatNumList;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public int getCabinId() {
return cabinId;
}
public void setCabinId(int cabinId) {
this.cabinId = cabinId;
}
}