栈和队列练习题

第一题(有效的括号)

给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
每个右括号都有一个对应的相同类型的左括号。
在这里插入图片描述

思路:我们可以用栈来做这道题,利用栈的先进后出特性,如果遇到左括号,直接入栈,如果遇到右括号,我们先判断栈是否为空,如果为空,则表明左括号多了,然后判断匹不匹配,如果匹配就继续,不匹配则退出。最后循环走完,出来再判断栈空不空,如果不空,说明右括号多了,也返回false,走到最后一步,说明匹配上了,则返回true,代码如下

    public boolean isValid(String s) {
        Stack<Character> list = new Stack<>();
        for(int i = 0;i < s.length();i++) {
            char ch = s.charAt(i);
            if(ch == '(' || ch == '{' || ch == '[') {
                list.push(ch);
            } else {
                //右括号多的情况
                if(list.empty()) {
                    return false;
                }
                char top = list.peek();
                if(top=='('&&ch==')' || top=='{'&&ch=='}' || top=='['&&ch==']') {
                    list.pop();
                } else {
                    //左右括号不匹配的情况
                    return false;
                }
            }
        }
        //左括号多的情况
        if(!list.empty()) {
            return false;
        }
        return true;
    }

第二题(用队列实现栈的功能)

在这里插入图片描述

用两个队列实现栈,思路:放的时候往不为空的队列放,如果都为空,则指定一个放。出的时候把不为空的队列里面size-1个弄出来放入为空的那一个,再看方法,方法是top,还是pop;记下值,如果是pop弹出然后返回值即可,如果是top,弹出然后放入另一个队列,再返回值即可,代码如下

在这里插入图片描述

/**
 * 用两个队列实现栈,思路:放的时候往不为空的队列放,如果都为空,则指定一个放
 * 出的时候把不为空的队列里面size-1个弄出来放入为空的那一个,再看方法,是方法
 * 是top,还是pop;记下值,如果是pop弹出然后返回值即可,如果是top,弹出然后放入
 * 另一个队列,再返回值即可
 */
public class MyStack {
    public Queue<Integer> qu1;
    public Queue<Integer> qu2;
    public MyStack() {
        this.qu1 = new LinkedList<>();
        this.qu2 = new LinkedList<>();
    }
    public void push(int x) {
        if(!qu1.isEmpty()) {                   //往不为空的一个队列放,如果都为空,则制定一个放
            qu1.offer(x);
        } else if(!qu2.isEmpty()) {
            qu2.offer(x);
        } else {
            qu1.offer(x);
        }
    }

    public int pop() {
        if(empty()) return -1;                  //把不为空的放入为空的,留下最后一个,最后记录然后弹出
        if(!qu1.isEmpty()) {
            int size = qu1.size();
            for (int i = 0;i < size-1;i++) {
                int a = qu1.peek();
                qu1.poll();
                qu2.offer(a);
            }
            int b = qu1.peek();
            qu1.poll();
            return b;
        } else {
            int size = qu2.size();
            for (int i = 0;i < size-1;i++) {
                int a = qu2.peek();
                qu2.poll();
                qu1.offer(a);
            }
            int b = qu2.peek();
            qu2.poll();
            return b;
        }
    }

    public int top() {
        if(empty()) return -1;                              //把不为空的放入为空的,留下最后一个,最后记录然后放入另一个队列
        if(!qu1.isEmpty()) {
            int size = qu1.size();
            int value = -1;
            for (int i = 0;i < size;i++) {
                value = qu1.peek();
                qu1.poll();
                qu2.offer(value);
            }
            return value;
        } else {
            int value = -1;
            int size = qu2.size();
            for (int i = 0;i < size;i++) {
                value = qu2.peek();
                qu2.poll();
                qu1.offer(value);
            }
            return value;
        }
    }
    public boolean empty() {
        return qu1.isEmpty() && qu2.isEmpty();
    }
}

第三题(用栈实现队列的功能)

在这里插入图片描述

用两个栈实现队列功能,放只管往前一个栈放,出的时候出第二个,如果第二个为空,就把第一个全取出来放入第二个,然后再出,怎么出具体看方法的要求,代码如下

在这里插入图片描述

/**
 * 用两个栈实现队列功能,放只管往前一个栈放,出的时候出第二个
 * 如果第二个为空,就把第一个全取出来放入第二个,然后再出,怎么出具体看
 * 方法的要求
 */
public class MyQueue {
    public Stack<Integer> stack1;
    public Stack<Integer> stack2;
    public MyQueue() {
        this.stack1 = new Stack<>();
        this.stack2 = new Stack<>();
    }
    public void push(int x) {
        stack1.push(x);
    }
    public int pop() {
        if(stack2.empty()) {
            int size = stack1.size();
            for (int i = 0;i < size ;i++) {
                int x= stack1.peek();
                stack1.pop();
                stack2.push(x);
            }
            int a = stack2.peek();
            stack2.pop();
            return a;
        } else {
            int a = stack2.peek();
            stack2.pop();
            return a;
        }
    }

    public int peek() {
        if(stack2.empty()) {
            int size = stack1.size();
            for (int i = 0;i < size ;i++) {
                int x= stack1.peek();
                stack1.pop();
                stack2.push(x);
            }
            int a = stack2.peek();
            return a;
        } else {
            int a = stack2.peek();
            return a;
        }
    }

    public boolean empty() {
        return stack1.empty() && stack2.empty();
    }
}

第四题(实现最小栈)

在这里插入图片描述

题目中重点是常数时间拿到最小元素。即O(1) 思路:利用辅助栈,即创建两个栈。一个为Stack,一个为MinStack;Stack功能一切正常。入栈时,需要判断这个值是否小于MinStack的最上面一个,如果MinStack为空,直接入到MinStack,否则判断大小,如果小于等于就入栈。接下来看出栈,如果出栈的值等于MinStack的peek,则MinStack也要出栈。最后top方法直接找Stack,getMin直接找MinStack即可O(1).代码如下

在这里插入图片描述

class MinStack {
    public Stack<Integer> Stack;
    public Stack<Integer> MinStack;

    public MinStack() {
        Stack = new Stack<>();
        MinStack = new Stack<>();
    }
    
    public void push(int val) {
        Stack.push(val);                  //入栈
        if(!MinStack.empty()) {    //不为空就要判断是否小于minStack或者等于上面一个
            int top = MinStack.peek();
            if(val <= top) {               //如过满足就放进去
                MinStack.push(val);
            }
        } else {
            MinStack.push(val);
        }
    }
    public void pop() {
        int top1 = Stack.peek();
        Stack.pop();
        if(!MinStack.empty()) {
            int top2 = MinStack.peek();
            if(top1 == top2) {
                MinStack.pop();
            }
        }

    } 
    public int top() {
        if(!Stack.empty()) {
            return Stack.peek();
        } throw new RuntimeException("栈中元素为空,此操作非法");
    }
    public int getMin() {
        if(!MinStack.empty()) {
            return MinStack.peek();
        } throw new RuntimeException("栈中元素为空,此操作非法");
    }
}

第五题(设计循环队列)

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

因为事例全是数字,我们用一个数组来实现。定义一个数组,一个front対首。一个rear队尾。这里我们判断满不满可以这样判断,耗费一个空间,如果rear的下一个位置是在front,即满了,如果相遇,则为空。所以构造函数创空间时,我们应该多创一个,才能放得完事例。代码如下

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

class MyCircularQueue {
    public int[] elem;
    public int front;  //头
    public int rear;   //尾

    public MyCircularQueue(int k) {
        this.elem = new int[k+1];
    }

    public boolean enQueue(int value) {
        if(isFull()) {            //插入需要判断满不满
            return false;
        }
        elem[rear] = value;
        rear = (rear+1) % elem.length;
        return true;
    }

    public boolean deQueue() {
        if(isEmpty()) {           //删除需要判断空不空
            return false;
        }
        front = (front+1) % elem.length;
        return true;
    }

    public int Front() {
        if(isEmpty()) {          //获取対首元素需要判断空不空
            return -1;
        }
        return elem[front];
    }

    public int Rear() {
        if(isEmpty()) {          //获取队尾判断空不空
            return -1;
        }
        if(rear == 0) {          //0下标退格与其他地方退格不一样
            return elem[elem.length-1];
        } else {
            return elem[rear-1];
        }
    }
    public boolean isEmpty() {
        if(rear == front) {
            return true;
        }
        return false;
    }

    public boolean isFull() {
        if((rear+1) % elem.length == front) {
            return true;
        }
        return false;
    }
}
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值