数据结构之栈

80 阅读2分钟

栈是Vector的一个子类,它实现了一个标准的后进先出的栈。

栈方法

  • 测试栈是否为空

boolean empty()

  • 查看栈顶的对象,但不从栈中移除

Object peek()

  • 移除栈顶的对象,并作为此函数的返回值

Object pop()

  • 把项压入栈顶

Object push(Object element)

  • 返回对象在栈中位置,以1为基数

int search(Object element)

栈创建

Stack<Integer> stack = new Stack<>();
Stack<Character> stack = new Stack<>();

栈使用

  1. 给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。

    有效字符串需满足:

    • 左括号必须用相同类型的右括号闭合。
    • 左括号必须以正确的顺序闭合。
    • 注意空字符串可被认为是有效字符串。

    解题思路:

    • 如果字符串是空串,奇数串,则无效

    • 使用栈结构,利用先进后出的特性

    • 进行对字符串中所有字符的遍历配对

      a, 从字符串中取出字符,判断字符类型(左侧 or 右侧)后,入栈 
      b, 针对右侧符号是否首先出来进行剔除判断 
      c, 将栈中字符pop,与字符串中数据进行比较
      

    参考代码:

    class Solution {
        public boolean isValid(String s) {
            Stack<Character> stack = new Stack<Character>();
            for(char c : s.toCharArray()){
                if(c == '(' || c == '{' || c == '['){
                    stack.push(c);
                }
                if(c == ')'){
                    if(stack.empty())
            return false;
                    char m = stack.pop();
                    if(m != '(') return false;
                }
                if(c == '}'){
                    if(stack.empty())
            return false;
                    char m = stack.pop();
                    if(m != '{') return false;
                }
                if(c == ']'){
                    if(stack.empty())
            return false;
                    char m = stack.pop();
                    if(m != '[') return false;
                }
            }
            if(stack.empty()){
                return true;
            }
            return false;
        }
    } 
    
    
  2. 大鱼吃小鱼的问题 在水中有许多的鱼,可以认为这些鱼停放在 x 轴上。再给定两个数组 Size,Dir,Size[i] 表示第 i 条鱼的大小,Dir[i] 表示鱼的方向(0 表示向左游,1 表示向右游)。 这两个数组分别表示鱼的大小和游动的方向,并且这两个数组的长度相等。 这些鱼的行为都符合以下几个条件∶

    1. 所有的鱼都同时开始游动,每次按照鱼的方向,都游动一个单位距离
    1. 当方向相对时,大鱼会吃掉小鱼
    1. 鱼的大小都不一样
    • 输入:Size=[4,2,5,3,1],Dir=[1,1,0,0,0]
    • 输出: 3
    • 请完成以下接口来计算还剩下几条鱼?
public static int solution(int[] fishSize,int[] fishDir){
    //鱼的数量
    int fishNum = fishSize.length;
    if (fishNum <= 1){
        return fishNum;
    }
    int left = 0;
    int right = 1;
    Stack<Integer> t = new Stack<>();
    for (int i = 0; i < fishNum; i++) {
        int curFishDirection = fishDir[i];
        int curFishSize = fishSize[i];
        //记录当前的鱼是否被吃掉
        boolean hasEat = false;

        while (!t.empty() && fishDir[t.peek()]==right && curFishDirection==left){
            if (fishSize[t.peek()] > curFishSize){
                hasEat = true;
                break;
            }
            t.pop();
        }
        if (!hasEat){
            t.push(i);
        }
    }
    return t.size();
}

总结:

  • 消除行为不同
    • 例1中,消除行为表现为配对的两者都会消除
    • 例2中,消除行为表现为配对的两者中有一个会被消除
  • 栈中的内容不同
    • 例1中,栈中的存放的就是内容本身
    • 例2中,栈中存放的只是内容的索引,可以通过索引得到内容

image.png