算法训练营Day10|栈与队列part01

232.用栈实现队列

  • 自我尝试
    • 思路: 用俩栈模拟队列是通过两个栈来实现的。一个定义为输入栈,一个为输出栈。
      • push: 添加元素,即可直接添加到输入栈里。
      • pop: 如果输出栈当前还有元素,直接pop操作就好。但是如果没有,就将所有输入栈元素,导出到输出栈里。随后输出栈一个pop操作。
      • peak:同样的,输出栈为准,使用栈的peek方法。
    • 代码
      // java有 Stack<类>
      
      
      class MyQueue {
          
          //two stacks
          Stack<Integer> sIn = new Stack<>();
          Stack<Integer> sOut = new Stack<>();
      
          public MyQueue() {
              sIn = new Stack<>();
              sOut = new Stack<>();
          }
          
          public void push(int x) {
              //add element
              sIn.push(x);
      
          }
          public void transit(){
              if(sOut.empty()){
                  while(!sIn.empty()){
                      sOut.push(sIn.pop());
                  }
              }
          }
          
          public int pop() {
              transit();
              return sOut.pop();
          }
          
          public int peek() {
              // return the element at the head of the queue
              transit();
              return sOut.peek();
          }
          
          public boolean empty() {
              // True when two stacks are both empty
              return sIn.empty()&&sOut.empty();
          }
      }
      
    • 收获:
      • Stack<>类:此类基于vector类实现的。
        • empty():复杂度O(1)
        • peek():复杂度O(1)
        • push():复杂度O(1),在内部需要调整大小时候可能为O(n)
        • search(object o):实现从vector末尾向前搜,复杂度O(n)
      • Vector类:
        • Vector内部使用动态数组来存储数据,可动态增删容量
        • 所有公共方法是同步的即线程安全
        • 容量增长每次x2

225. 用队列实现栈

  • 自我尝试
    • 思路: 两个queue,一个拷贝,一个储存相同的元素, queue里的顺序与要实现的stack相反。
      • pop的话,通过size()方法,抓到最后一个元素,也就是top,赋值后,将copy queue里的元素再返回回去。
      • top的话类似,声明一个中间变量不停的变换。最后直接输出。
    • 代码
      class MyStack {
          // 思路,一个queue先进去元素,然后
          Queue<Integer> qMain;
          Queue<Integer> qCopy;
      
          public MyStack() {
           qMain = new LinkedList<>();
           qCopy = new LinkedList<>();
          }
          
          public void push(int x) {
              qMain.offer(x);
          }
          
          public int pop() {
              int size = qMain.size();
              for(int i=0;i<size-1;i++){
                  qCopy.offer(qMain.poll());
              }
              int result = qMain.poll();
              while(!qCopy.isEmpty()){
                  qMain.offer(qCopy.poll());
              }
              return result;
          }
          
          public int top() {
              int top=0;
              int size = qMain.size();
              for(int i=0;i<size;i++){
                  top = qMain.poll();
                  qCopy.offer(top);
              }
              while(!qCopy.isEmpty()){
                  qMain.offer(qCopy.poll());
              }
              return top;
          }
          
          public boolean empty() {
              return qMain.isEmpty();
          }
      }
      

    • 收获
      • 泛型类与泛型接口
        • Stack<E>:是一个泛型具体类。
        • Queue<E>:是一个接口,Queue<Integer>是一个泛型实例接口。
      • Arraylist与LinkedList关系
        • 内部结构: Arraylist是连续的动态数组。当容量超过当前极限,将会重新分配一个更大的; Linkedlist则是双链表储存结构
        • 性能:
          • 访问:Arraylist是O(1),而linkedlist需要O(n),即遍历整个数组
          • 添删:
            • 中间
              • Arraylist:O(n)
              • LinkedList: O(n), 因为要遍历找到那个位置先
            • 头:
              • Arraylist:O(n)
              • LinkedList:O(1)
            • 尾:
              • Arraylist: O(1) 不扩容的情况下
              • LinkedList: O(1)
        • 使用场景:
          • 如果经常在列表的开头/结尾操作的话,用linkedlist
      • 当while/for里的i<a.size()时候要注意,尤其是循环里涉及对a里元素更改时候。
  • 范例代码
    • 思路: 将qMain保持与stack一样的元素顺序。pop,peak等方法就十分便利。
    • 代码
      class MyStack {
          // 思路,一个queue先进去元素,然后
          Queue<Integer> qMain;
          Queue<Integer> qCopy;
      
          public MyStack() {
           qMain = new LinkedList<>();
           qCopy = new LinkedList<>();
          }
          
          public void push(int x) {
             //如果main里有元素,先pop到qCopy里
             while(!qMain.isEmpty()){
                 qCopy.offer(qMain.poll());
             }
             
             //添加元素,这样它保证再队列头部
             qMain.add(x);
             //将余下元素放进来
             while(!qCopy.isEmpty()){
                 qMain.offer(qCopy.poll());
             }
          }
          
          public int pop() {
              return qMain.poll();
          }
          
          public int top() {
              return qMain.peek();
          }
          
          public boolean empty() {
              return qMain.isEmpty();
          }
      }
      

    • 收获
      • Queue<T>接口方法:
        • poll():移除队列的头部元素,若为空返回null
        • peek():检查头部元素,并不删除。
        • add(E e): 尝试将元素添加到队列。如果成功则返回 true。如果没有空间,则抛出 IllegalStateException
        • offer(E e): 尝试将元素添加到队列。如果成功则返回 true,如果没有空间则返回 false。
      • 两种实现比较:
        • 执行时间:
          • 自我方法:push-> O(1), top->O(n), pop->O(n);
          • 范例: push->O(n), top->O(1)[本质查询链表第一个元素], pop->O(1)[本质链表移除第一个元素];
        • 空间:
          • 大致相同

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值