剑指offer打卡Day18 栈的压入、弹出序列(重新学习 Vector 与 Stack)

剑指offer打卡Day18: 栈的压入、弹出序列

题目描述

输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)

示例

输入

[1,2,3,4,5],[4,3,5,1,2]

返回值

false

解析:

栈是非常基础的一种数据结构,不过在铲屎工作中用的不多,特地复习下,Crtl+ 点击源码,好家伙,一上来就是public class Stack<E> extends Vector<E>,那只能从Vector开始看起

  • Vector

    • Vector原意:矢量、向量,因此一般称作矢量队列,查看其源码

      public class Vector<E>
          extends AbstractList<E>
          implements List<E>, RandomAccess, Cloneable, java.io.Serializable
      

      可得:

      1. 继承了AbstractList,实现了List,所以,它是一个队列,支持相关的添加、删除、修改、遍历等功能
      2. 实现了RandmoAccess接口,即提供了随机访问功能
        • RandmoAccess是java中用来被List实现,为List提供快速访问功能的。
        • 在Vector中,我们即可以通过元素的序号快速获取元素对象;这就是快速随机访问。
      3. 实现了Cloneable接口,即实现clone()函数。它能被克隆。
      4. 同是list,但ArrayList不同,可由代码中的synchronized 得知 Vector中的操作是线程安全的
    • Vector 继承关系:

      java.lang.Object
         ↳     java.util.AbstractCollection<E>
               ↳     java.util.AbstractList<E>
                     ↳     java.util.Vector<E>
      

      Vector的数据结构和ArrayList差不多,它包含了3个成员变量:elementData , elementCount, capacityIncrement。

      1. elementData 是"Object[]类型的数组",它保存了添加到Vector中的元素。elementData是个动态数组,如果初始化Vector时,没指定动态数组的>大小,则使用默认大小10。随着Vector中元素的增加,Vector的容量也会动态增长,capacityIncrement是与容量增长相关的增长系数,具体的增长方式,请参考源码分析中的ensureCapacity()函数。
      2. elementCount 是动态数组的实际大小。
      3. capacityIncrement 是动态数组的增长系数。如果在创建Vector时,指定了capacityIncrement的大小;则,每次当Vector中动态数组容量增加时>,增加的大小都是capacityIncrement。
    • Vector的构造函数

      // 默认构造函数,创建一个默认的向量,默认大小为 10;
      public Vector()
      
      // capacity是Vector的默认容量大小。当由于增加数据导致容量增加时,每次容量会增加一倍。
      public Vector(int capacity)
      
      // capacity是Vector的默认容量大小,capacityIncrement是每次Vector容量增加时的增量值。
      public Vector(int capacity, int capacityIncrement)
      
      // 创建一个包含collection的Vector
      public Vector(Collection<? extends E> collection)
      
    • Vector 常用API实例汇总

      public class VectorDemo {
      
          public static void main(String args[]) {
              // initial size is 3, increment is 2
              Vector v = new Vector(3, 2);
              System.out.println("Initial size(容量大小): " + v.size());
              System.out.println("Initial capacity(增长系数): " + v.capacity());
              v.addElement(1);
              v.addElement(2);
              v.addElement(3);
              v.addElement(4);
              System.out.println("Capacity after four additions(增加四种元素后的容量为): " + v.capacity());
      
              v.addElement(5.45);
              System.out.println("Current capacity(当前容量): " + v.capacity());
              v.addElement(6.08);
              v.addElement(7);
              System.out.println("Current capacity(当前容量): " +v.capacity());
              v.addElement(9.4f);
              v.addElement(10);
              System.out.println("Current capacity(当前容量): " +v.capacity());
              v.addElement(11);
              v.addElement(12);
              System.out.println("First element(首元素): " + v.firstElement());
              System.out.println("Last element:(末元素)" + v.lastElement());
              if(v.contains(3))//判断是否包含
                  System.out.println("Vector contains 3.");
      
              // 遍历vector enumerate the elements in the vector.
              Enumeration vEnum = v.elements();
              System.out.println("\nElements in vector:");
              while(vEnum.hasMoreElements())
                  System.out.print(vEnum.nextElement() + " ");
          }
      }
      
      Initial size(容量大小): 0
      Initial capacity(增长系数): 3
      Capacity after four additions(增加四种元素后的容量为): 5
      Current capacity(当前容量): 5
      Current capacity(当前容量): 7
      Current capacity(当前容量): 9
      First element(首元素): 1
      Last element:(末元素)12
      Vector contains 3.
      
      Elements in vector:
      1 2 3 4 5.45 6.08 7 9.4 10 11 12 
      
  • Stack

    • Stack是栈。它的特性是:先进后出(FILO, First In Last Out)。

      java.lang.Object
      ↳     java.util.AbstractCollection<E>
         ↳     java.util.AbstractList<E>
             ↳     java.util.Vector<E>
                 ↳     java.util.Stack<E>
      public class Stack<E> extends Vector<E> {}
      

      由于Vector是通过数组实现的,这就意味着,Stack也是通过数组实现的

    • 构造函数

      Stack只有一个默认构造函数,如下:

      Stack()
      
    • 常用API

      由于Stack和继承于Vector,因此它也包含Vector中的全部API

                   boolean     empty()    //测试堆栈是否为空。
      synchronized E           peek()     //查看堆栈顶部的对象,但不从堆栈中移除它。
      synchronized E           pop()      //移除堆栈顶部的对象,并作为此函数的值返回该对象。
                   E           push(E object)  //把项压入堆栈顶部。
      synchronized int         search(Object o)  //返回对象在堆栈中的位置,以 1 为基数。
      
    • 源码

      没想到源码这么短,分析一波好了。

      public class Stack<E> extends Vector<E> {
          
          public Stack() {
          }
          
      	// push函数:将元素存入栈顶  
          public E push(E item) {
              // 将元素存入栈顶。
      		// addElement()的实现在Vector.java中
              addElement(item);
              return item;
          }
      
          // pop函数:返回栈顶元素,并将其从栈中删除
          public synchronized E pop() {
              E       obj;
              int     len = size();
              obj = peek();
               // 删除栈顶元素,removeElementAt()的实现在Vector.java中
              removeElementAt(len - 1);
              return obj;
          }
      	// peek函数:返回栈顶元素,不执行删除操作
          public synchronized E peek() {
              int     len = size();
              if (len == 0)
                  throw new EmptyStackException();
              // 返回栈顶元素,elementAt()具体实现在Vector.java中
              return elementAt(len - 1);
          }
      
          // 栈是否为空
          public boolean empty() {
              return size() == 0;
          }
      
         // 查找“元素o”在栈中的位置:由栈底向栈顶方向数
          public synchronized int search(Object o) {
              int i = lastIndexOf(o);
              // 获取元素索引,elementAt()具体实现在Vector.java中
              if (i >= 0) {
                  return size() - i;
              }
              return -1;
          }
          
          /** use serialVersionUID from JDK 1.0.2 for interoperability */
          private static final long serialVersionUID = 1224463164541339165L;
      }
      
  • 回到题目

    搞了那么久都差点忘了题目要我们干啥了

    • 既然要我们入栈,就构建个栈将序列推入

    • 并遍历所给的弹出序列,对比入栈的peek是都等于序列的值

    • 示意图:

      • 入栈
        在这里插入图片描述

      • 比较
        在这里插入图片描述

      • 遍历
        在这里插入图片描述

    • 最后查看栈内是否为空即可

解答:

public boolean IsPopOrder(int[] pushA, int[] popA) {
    if (pushA.length == 0 || popA.length == 0)
        return false;
    //辅助栈,用来push入栈序列
    Stack<Integer> assistStack = new Stack<Integer>();
    //用于标识弹出序列的位置
    int target = 0;
    for (int i = 0; i < pushA.length; i++) {
        assistStack.push(pushA[i]);
        //如果栈不为空,且栈顶元素等于目标的弹出序列
        while (!assistStack.empty() && assistStack.peek() == popA[target]) {
            //出栈
            assistStack.pop();
            //弹出序列向后一位
            target++;
        }
    }
    return assistStack.empty();
}

扩展:

  1. Java 集合系列06之 Vector详细介绍(源码解析)和使用示例
  2. java之Stack详细介绍
  3. Java Vector 类
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值