1670. 设计前中后队列

1670. 设计前中后队列

1670. 设计前中后队列

难度中等

请你设计一个队列,支持在前,中,后三个位置的 pushpop 操作。

请你完成 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
  • 最多调用 1000pushFrontpushMiddlepushBackpopFrontpopMiddlepopBack

分析

使用两个队列,保持大小相当,第一个队列最多比第二个队列多一个元素,所有操作都会是常数级复杂度。

type FrontMiddleBackQueue struct {
    left, right *list.List
}


func Constructor() FrontMiddleBackQueue {
    return FrontMiddleBackQueue{left:list.New(), right:list.New()}
}


func (q *FrontMiddleBackQueue) PushFront(val int)  {
    q.left.PushFront(val)
    if q.left.Len() > q.right.Len()+1 {
        q.right.PushFront(q.left.Remove(q.left.Back()))
    }
}


func (q *FrontMiddleBackQueue) PushMiddle(val int)  {
    // 与其他方法不同,先判断长度后 push
    if q.left.Len() == q.right.Len()+1 {
        q.right.PushFront(q.left.Remove(q.left.Back()))
    }
    q.left.PushBack(val)
}


func (q *FrontMiddleBackQueue) PushBack(val int)  {
    q.right.PushBack(val)
    if q.left.Len() < q.right.Len() {
        q.left.PushBack(q.right.Remove(q.right.Front()))
    }
}


func (q *FrontMiddleBackQueue) PopFront() int {
    if q.left.Len() == 0 {
        return -1
    }
    res := q.left.Remove(q.left.Front()).(int)
    if q.left.Len() < q.right.Len() {
        q.left.PushBack(q.right.Remove(q.right.Front()))
    }
    return res
}


func (q *FrontMiddleBackQueue) PopMiddle() int {
    if q.left.Len() == 0 {
        return -1
    }
    res := q.left.Remove(q.left.Back()).(int)
    if q.left.Len() < q.right.Len() {
        q.left.PushBack(q.right.Remove(q.right.Front()))
    }
    return res
}


func (q *FrontMiddleBackQueue) PopBack() int {
    if q.left.Len() == 0 {
        return -1
    }
    if q.right.Len() == 0 {
        return q.left.Remove(q.left.Back()).(int)
    }
    res := q.right.Remove(q.right.Back()).(int)
    if q.left.Len() > q.right.Len() +1 {
        q.right.PushFront(q.left.Remove(q.left.Back()))
    }
    return res
}