232. 用栈实现队列

题目

请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(pushpoppeekempty):

实现 MyQueue 类:

  • void push(int x) 将元素 x 推到队列的末尾
  • int pop() 从队列的开头移除并返回元素
  • int peek() 返回队列开头的元素
  • boolean empty() 如果队列为空,返回 true ;否则,返回 false

说明:

  • 只能 使用标准的栈操作 —— 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。
  • 你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。

示例 1:
输入:
[“MyQueue”, “push”, “push”, “peek”, “pop”, “empty”]
[[], [1], [2], [], [], []]
输出:
[null, null, null, 1, 1, false]
解释:
MyQueue myQueue = new MyQueue();
myQueue.push(1); // queue is: [1]
myQueue.push(2); // queue is: [1, 2] (leftmost is front of the queue)
myQueue.peek(); // return 1
myQueue.pop(); // return 1, queue is [2]
myQueue.empty(); // return false

提示:

  • 1 <= x <= 9
  • 最多调用 100pushpoppeekempty
  • 假设所有操作都是有效的 (例如,一个空的队列不会调用 pop 或者 peek 操作)

解题思路

队列是先进先出(FIFO)的数据结构,而栈是后进先出(LIFO)的。
通过在两个栈之间倒腾元素,实现了元素顺序的反转,从而把栈的LIFO特性转变为队列的FIFO特性。

基本思路:

  1. 使用两个栈(可以称为"输入栈"和"输出栈")
  2. push操作:直接将元素压入输入栈
  3. poppeek操作:
    • 如果输出栈为空,则将输入栈中的所有元素依次弹出并压入输出栈(这样元素的顺序就被反转了)
    • 从输出栈取出栈顶元素(对于队列来说就是最先进入的元素)
  4. empty操作:当两个栈都为空时,队列为空

需要注意的是,为了保证队列操作的正确性,我们只在必要的时候(输出栈为空时)才将输入栈的元素转移到输出栈。

代码


typedef struct {
    int* stack1;    // 输入栈
    int* stack2;    // 输出栈
    int top1;       // 输入栈顶索引
    int top2;       // 输出栈顶索引
    int capacity;   // 栈的容量
} MyQueue;


MyQueue* myQueueCreate() {
    MyQueue* queue = (MyQueue*)malloc(sizeof(MyQueue));
    queue->capacity = 100;  // 设置一个初始容量,可以根据需要调整
    queue->stack1 = (int*)malloc(sizeof(int) * queue->capacity);
    queue->stack2 = (int*)malloc(sizeof(int) * queue->capacity);
    queue->top1 = -1;
    queue->top2 = -1;
    return queue;
}

// 将输入栈的元素移动到输出栈
void shiftStacks(MyQueue* obj) {
    if (obj->top2 == -1) {  // 只有当输出栈为空时才移动
        while (obj->top1 >= 0) {
            obj->stack2[++obj->top2] = obj->stack1[obj->top1--];
        }
    }
}

void myQueuePush(MyQueue* obj, int x) {
    // 检查是否需要扩容
    if (obj->top1 + 1 >= obj->capacity) {
        obj->capacity *= 2;
        obj->stack1 = (int*)realloc(obj->stack1, sizeof(int) * obj->capacity);
        obj->stack2 = (int*)realloc(obj->stack2, sizeof(int) * obj->capacity);
    }

    // 将元素压入输入栈
    obj->stack1[++obj->top1] = x;
}

int myQueuePop(MyQueue* obj) {
    // 确保输出栈有元素
    shiftStacks(obj);

    // 从输出栈弹出元素
    int temp = obj->stack2[obj->top2];
    obj->top2 -= 1;
    return temp;
}

int myQueuePeek(MyQueue* obj) {
    // 确保输出栈有元素
    shiftStacks(obj);

    // 返回但不删除
    return obj->stack2[obj->top2];
}

bool myQueueEmpty(MyQueue* obj) {
    // 当两个栈都为空时,队列为空
    return (obj->top1 == -1 && obj->top2 == -1);
}

void myQueueFree(MyQueue* obj) {
    // 释放栈内存
    free(obj->stack1);
    free(obj->stack2);
    // 释放队列结构体
    free(obj);
}

/**
 * Your MyQueue struct will be instantiated and called as such:
 * MyQueue* obj = myQueueCreate();
 * myQueuePush(obj, x);
 
 * int param_2 = myQueuePop(obj);
 
 * int param_3 = myQueuePeek(obj);
 
 * bool param_4 = myQueueEmpty(obj);
 
 * myQueueFree(obj);
*/

改进代码

你可能感兴趣的:(力扣刷题,算法,数据结构,leetcode,c语言)