题目描述
请你设计一个队列,支持在前,中,后三个位置的 push 和 pop 操作。
请你完成 FrontMiddleBack 类:
FrontMiddleBack()初始化队列。void pushFront(int val)将val添加到队列的 最前面 。void pushMiddle(int val)将val添加到队列的 正中间 。void pushBack(int val)将val添加到队里的 最后面 。int popFront()将 最前面 的元素从队列中删除并返回值,如果删除之前队列为空,那么返回-1。int popMiddle()将 正中间 的元素从队列中删除并返回值,如果删除之前队列为空,那么返回-1。int popBack()将 最后面 的元素从队列中删除并返回值,如果删除之前队列为空,那么返回-1。
请注意当有 两个 中间位置的时候,选择靠前面的位置进行操作。比方说:
- 将
6添加到[1, 2, 3, 4, 5]的中间位置,结果数组为[1, 2, 6, 3, 4, 5]。 - 从
[1, 2, 3, 4, 5, 6]的中间位置弹出元素,返回3,数组变为[1, 2, 4, 5, 6]。
示例 1:
输入:
["FrontMiddleBackQueue", "pushFront", "pushBack", "pushMiddle", "pushMiddle", "popFront", "popMiddle", "popMiddle", "popBack", "popFront"]
[[], [1], [2], [3], [4], [], [], [], [], []]
输出:
[null, null, null, null, null, 1, 3, 4, 2, -1]
解释:
FrontMiddleBackQueue q = new FrontMiddleBackQueue();
q.pushFront(1); // [1]
q.pushBack(2); // [1, 2]
q.pushMiddle(3); // [1, 3, 2]
q.pushMiddle(4); // [1, 4, 3, 2]
q.popFront(); // 返回 1 -> [4, 3, 2]
q.popMiddle(); // 返回 3 -> [4, 2]
q.popMiddle(); // 返回 4 -> [2]
q.popBack(); // 返回 2 -> []
q.popFront(); // 返回 -1 -> [] (队列为空)
提示:
1 <= val <= 109- 最多调用
1000次pushFront,pushMiddle,pushBack,popFront,popMiddle和popBack。
代码
class FrontMiddleBackQueue {
private int[] pre, pst;
private int prePre, prePst, pstPre, pstPst;
private static final int max = 3000;
public FrontMiddleBackQueue() {
this.pre = new int[max];
this.pst = new int[max];
this.prePre = this.prePst = this.pstPre = this.pstPst = 0;
}
// 维护数组长度
private void maintain(){
int x = pstSize() - preSize();
// 后比前长过1,后补前
if(x > 1) pushPreBack(popPstFront());
// 前比后长,前补后
else if(x < 0) pushPstFront(popPreBack());
}
private boolean preEmpty(){
if(this.prePst == this.prePre) return true;
return false;
}
private boolean pstEmpty(){
if(this.pstPst == this.pstPre) return true;
return false;
}
// 前半段长度
private int preSize(){
if(this.prePst >= this.prePre) return this.prePst - this.prePre;
else return max - this.prePre + this.prePst;
}
// 后半段长度
private int pstSize(){
if(this.pstPst >= this.pstPre) return this.pstPst - this.pstPre;
else return max -this.pstPre + this.pstPst;
}
// 前插,先存后移
public void pushFront(int val) {
this.pre[this.prePst] = val;
this.prePst = (this.prePst + 1) % max;
maintain();
}
// 插入前半段的后插,先移后存
private void pushPreBack(int val){
this.prePre = this.prePre == 0 ? max - 1: this.prePre - 1;
this.pre[this.prePre] = val;
}
// 中插
public void pushMiddle(int val) {
if(preSize() < pstSize()) pushPreBack(val);
else pushPstFront(val);
maintain();
}
// 后插,先存后移
public void pushBack(int val) {
this.pst[this.pstPst] = val;
this.pstPst = (this.pstPst + 1) % max;
maintain();
}
// 插入后半段的前插,先移后存
private void pushPstFront(int val){
this.pstPre = this.pstPre == 0 ? max - 1: this.pstPre - 1;
this.pst[this.pstPre] = val;
}
// 先移再返回
public int popFront() {
if(preEmpty()) {
if(pstEmpty()) return -1;
return popPstFront();
}
if(this.prePst == 0) this.prePst = max;
this.prePst--;
maintain();
return this.pre[this.prePst];
}
// 前半段的后面,先返回再移动
private int popPreBack(){
int flag = this.prePre;
this.prePre = (this.prePre + 1) % max;
return this.pre[flag];
}
public int popMiddle() {
if(pstEmpty() && preEmpty()) return -1;
if(preSize() < pstSize()) return popPstFront();
else return popPreBack();
}
// 先移再返回
public int popBack() {
if(pstEmpty()) {
if(preEmpty()) return -1;
return popPreBack();
}
if(this.pstPst == 0) this.pstPst = max;
this.pstPst--;
maintain();
return this.pst[this.pstPst];
}
// 后半段的前面,先返回再移动
private int popPstFront(){
int flag = this.pstPre;
this.pstPre = (this.pstPre + 1) % max;
return this.pst[flag];
}
// 方便debug
public void show(){
System.out.println("--------------------------------------------------------");
System.out.println("前半段:头指针->"+this.prePst + ", 尾指针->" + this.prePre + ", 长度:" + preSize());
System.out.println("后半段:头指针->"+this.pstPst + ", 尾指针->" + this.pstPre + ", 长度:" + pstSize());
System.out.print("前:");
for (int i = this.prePst; i != this.prePre; ) {
if(preEmpty()) break;
i = i == 0 ? max - 1 : i - 1;
System.out.print(" ("+ this.pre[i] +")");
}
System.out.print(" || 后:");
if(pstEmpty()) {
System.out.println("\n--------------------------------------------------------");
return;
}
for (int i = this.pstPre;;) {
System.out.print(" ("+ this.pst[i] +")");
i = (i + 1) % max;
if(i == this.pstPst) break;
}
System.out.println("\n--------------------------------------------------------");
}
}