初级3 题目三 如何仅用队列结构实现栈结构?如何仅用栈结构实现队列结构?(LeetCode 232, 235)

1. 队列结构实现栈结构

        使用队列实现栈结构,核心思想为功能分割。第一种方法是使用两个队列,流程如下图所示:

        压栈时,直接进入 Data 队列即可。出栈时,Data 队列每次仅保留队尾一个元素,其他元素全部进入 Help 队列中,这时返回给用户 Data 队列中仅有的元素值。之后 Data 队列的元素弹出,并将 Data 和 Help 的地址互换,重复执行上述操作。(永远对 Data 队列进行操作

#include <iostream>
#include <queue>

using namespace std;

// 方法一,使用两个队列模拟栈
class MyStack {
 public:

  queue<int> Data;
  queue<int> Help;

  // 进入元素直接进入 Data 队列,删除元素只在 Data 队列仅有一个元素时才删除

  /** Initialize your data structure here. */
  MyStack() {

  }

  /** Push element x onto stack. */
  void push(int x) {
    Data.push(x);
  }

  /** Removes the element on top of the stack and returns that element. */
  int pop() {

    // 如果队列空
    if(Data.empty()){
      return -1;
    }

    // 将 Data 队列元素移至 Help 队列,Data 队列只剩下队尾元素即可
    while(Data.size() != 1){
      Help.push(Data.front());
      Data.pop();
    }

    // 此时Data队列仅剩一个元素,将其弹出
    int pop_number = Data.back();
    Data.pop();

    // 交换 Data 和 Help 的地址
    swap(Data, Help);

    return pop_number;
  }

  /** Get the top element. */
  int top() {
    return Data.back();
  }

  /** Returns whether the stack is empty. */
  bool empty() {
    return Data.empty();
  }
};

        复杂度分析

                时间复杂度:压栈时,元素直接进入队列,O(1) 操作。出栈时,每次需要移动 n-1 个元素,故时间复杂度为 O(n)获取栈顶元素和判断栈空均为 O(1) 操作

                空间复杂度:使用了两个队列,故空间复杂度为 O(n)

        方法二,使用一个队列模仿栈结构https://leetcode-cn.com/problems/implement-stack-using-queues/solution/yong-dui-lie-shi-xian-zhan-by-leetcode-solution/)。 核心思想为,栈顶指针永远指向最新的元素。从此角度考虑,需要将新入队的元素始终保持队首位置。故在新元素入队前,记录此时队列中元素个数。在新元素入队后,新元素前面的所有元素全部出队而后重新入队,此时新元素在队首位置。

#include <iostream>
#include <queue>

using namespace std;

// 使用一个队列模拟栈
class MyStack {
 public:

  queue<int> Data;

  // 一个队列模拟栈,每次入队之前,记录队中元素个数,然后这些元素先出队,让最新进入的元素到达队首
  // 核心思想是:栈顶指针永远指向最新进入的元素

  // Data 就是一个栈,只不过压栈特殊些

  /** Initialize your data structure here. */
  MyStack() {

  }

  /** Push element x onto stack. */
  void push(int x) {

    int count = Data.size(); // 获取队列中已有的元素个数

    Data.push(x);

    // count 个元素先出队,再入队
    while(count != 0){
      int temp = Data.front();
      Data.pop();
      Data.push(temp);
      count--;
    }
  }

  /** Removes the element on top of the stack and returns that element. */
  int pop() {
    int pop_number = Data.front();
    Data.pop();
    return pop_number;
  }

  /** Get the top element. */
  int top() {
    return Data.front();
  }

  /** Returns whether the stack is empty. */
  bool empty() {
    return Data.empty();
  }
};

        复杂度分析

                时间复杂度:由于每次进入新元素时,需要移动 n-1 个元素,故入栈操作 O(n)。其他操作均为 O(1)。

                空间复杂度: 使用了一个队列,故空间复杂度 O(n)。

2. 栈结构实现队列结构

        使用栈实现队列结构,核心思想仍为功能分割。创建两个栈,push 栈和 pop 栈。用户的输入永远放入 push 栈,pop 栈永远只向用户输出。例如用户输入 1 2 3 4 5,那么将该数全部压入 push 栈,用户取数时将 push 栈内容全部压入 pop 栈,取数时即为 1 2 3 4 5。

        输入直接压入 push 栈,输出则借助 pop 栈。但要注意两点:

                1)push 栈元素在压入 pop 栈之前,一定要确保 pop 栈内无元素,是个空栈

                2)每次 push 栈压入到 pop 栈时,一定要把所有元素一次性压完

// 剑指 Offer 09 用两个栈实现队列
class CQueue {

    // s.empty() 如果栈为空返回true,否则返回false
    // s.size() 返回栈中元素的个数
    // s.pop() 删除栈顶元素但不返回其值
    // s.top() 返回栈顶的元素,但不删除该元素
    // s.push() 在栈顶压入新元素

    // 核心思想:功能分割
    stack<int> stack_push, stack_pop;
public:
    CQueue() {
        
    }
    
    // push 栈只用来压数据
    void appendTail(int value) {
        stack_push.push(value);
    }
    
    // pop 栈用来弹数据
    int deleteHead() {
        
        // 如果 pop 栈空
        if(stack_pop.empty()){
            
            // 如果push栈也空,直接-1
            if(stack_push.empty()){  
                return -1;

            }else{ // 如果 push 栈不空,那把 push 栈的所有数据弹到 pop 栈
                while(!stack_push.empty()){
                    stack_pop.push(stack_push.top());
                    stack_push.pop(); // 删除栈顶元素
                }
            }   
        }
        
        // 此时 pop 栈一定不空,直接返回即可
        int delete_value = stack_pop.top();
        stack_pop.pop();
        return delete_value;
    }
};

        复杂度分析:(链接:https://leetcode-cn.com/problems/yong-liang-ge-zhan-shi-xian-dui-lie-lcof/solution/mian-shi-ti-09-yong-liang-ge-zhan-shi-xian-dui-l-3/

                时间复杂度:对于插入和删除操作,时间复杂度均为 O(1)。插入不多说,对于删除操作,虽然看起来是 O(n) 的时间复杂度,但是仔细考虑下每个元素只会「至多被插入和弹出 pop 栈 一次」,因此均摊下来每个元素被删除的时间复杂度仍为 O(1)

                空间复杂度O(n)。需要使用两个栈存储已有的元素。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值