栈和队列的使用以及相关的Oj题

1. 栈(stack)

1.1概念

自己的理解:一种线性表,只能从一端插入,删除元素,遵循先进后出的原则;

标准定义:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。

压栈:栈的插入操作叫做压栈;
出栈:也称弹栈,栈的删除操作叫做出栈;

1.2 栈的实现

//利用顺序表实现
public class MyStack {
    int [] array;
    int size;
    MyStack(){
        //不考虑扩容问题
        this.array=new int[100];
        this.size=0;
    }
    public void push(int val){
        this.array[size++]=val;
    }
    public int pop(){
        return array[--size];
    }
    public int peek(){
        return array[size-1];
    }
    public boolean isEmpty(){
        return size==0;
    }
    public int size(){
        return size;
    }
}

2.队列(queue)

2.1概念

队列:只允许在一端进行插入操作,在另一端进行删除操作的顺序表,遵循先进先出原则;
入队列:进行插入操作的一端称为队尾
出队列:进行删除操作的一端称为队头

2.2 实现

class  Node{
    Node next;
    int val;
    Node(int val){
        this.val=val;
    }
}
//使用链表实现,数组实现的队列在进行出队列时时间复杂度太大
public class MyQueue {
    private Node head;
    private Node tail;
    private int size;
    MyQueue(){
        this.head=null;
        this.tail=null;
        this.size=0;
    }
    public void offer(int val){
        Node node=new Node(val);
        if(head==null){
            head=node;
        }else{
            tail.next=node;
        }
        tail=node;
        size++;
    }
    public int poll(){
        if(size==0){
            throw new RuntimeException("队列为空!");
        }
        int v=head.val;
        head=head.next;
        //当队列中只有一个元素的时候,将尾结点置空
        if(head==null){
            tail=null;
        }
        size--;
        return v;
    }
    public int peek(){
       if(size==0){
           throw new RuntimeException("队列为空");
       }
       return head.val;
    }
    public boolean isEmpty(){
        return size==0;
    }
    public int size(){
        return size;
    }
}

2.3 循环队列

2.3.1实现:循环队列通常使用数组来实现

class MyCircularQueue {
//    MyCircularQueue(k): 构造器,设置队列长度为 k 。
//    Front: 从队首获取元素。如果队列为空,返回 -1 。
//    Rear: 获取队尾元素。如果队列为空,返回 -1 。
//    enQueue(int value): 向循环队列插入一个元素。如果成功插入则返回真。
//    deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。
//    isEmpty(): 检查循环队列是否为空。
//    isFull(): 检查循环队列是否已满。
    private final int []queue;
    private int size;
    private int FrontIndex;
    private int rearIndex;
    /** Initialize your data structure here. Set the size of the queue to be k. */
    public MyCircularQueue(int k) {
        this.queue=new int[k];
        this.size=0;
        this.FrontIndex=0;
        this.rearIndex=0;
    }
    /** Insert an element into the circular queue. Return true if the operation is successful. */
    public boolean enQueue(int value) {
       if(this.size==this.queue.length){
           return false;
       }
       this.queue[rearIndex]=value;
       this.rearIndex++;
       size++;
       if(this.rearIndex==this.queue.length){
           this.rearIndex=0;
       }
        return true;
    }
    /** Delete an element from the circular queue. Return true if the operation is successful. */
    public boolean deQueue() {
        if(this.size==0){
            return false;
        }
        size--;
        this.FrontIndex++;
        if(FrontIndex==this.queue.length){
            FrontIndex=0;
        }
       return true;
    }
    /** Get the front item from the queue. */
    public int Front() {
        if(size==0){
            return -1;
        }
        return this.queue[FrontIndex];
    }
    /** Get the last item from the queue. */
    public int Rear() {
        if(size==0){
            return -1;
        }
        int index=this.rearIndex-1;
        if(index==-1){
            index=this.queue.length-1;
        }
        return this.queue[index];
    }
    /** Checks whether the circular queue is empty or not. */
    public boolean isEmpty() {
        return this.size==0;
    }
    /** Checks whether the circular queue is full or not. */
    public boolean isFull() {
        return this.size==this.queue.length;
    }
}

3.面试题

1.力扣 20题(有效的括号)
链接

给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
注意空字符串可被认为是有效字符串。
示例 1:
输入: “()”
输出: true
示例 2:
输入: “()[]{}”
输出: true
示例 3:
输入: “(]”
输出: false
示例 4:
输入: “([)]”
输出: false
示例 5:
输入: “{[]}”
输出: true
来源:力扣(LeetCode)

class Solution {
    public  boolean isValid(String s) {
        if(s.isEmpty()){
            return false;
        }
        char [] c=s.toCharArray();
        Deque<Character> Stack=new LinkedList<>();
        for (char c1:c) {
            switch (c1){
                case '(':
                case '[':
                case '{':
                    Stack.push(c1);
                    break;
                default:
                    //一定是右括号
                    if(Stack.isEmpty()){
                        return false;
                    }
                    if(!compare(Stack.pop(),c1)){
                     return false;
                    }

            }
        }
        if(Stack.isEmpty()){
            return true;
        }
        return false;
    }

    private boolean compare(char pop, char c1) {
        if(pop=='['&&c1==']'){
            return true;
        }
        if(pop=='('&&c1==')'){
            return true;
        }if(pop=='{'&&c1=='}'){
            return true;
        }
        return false;
    }
}

力扣225. 用队列实现栈
链接

push(x) – 元素 x 入栈
pop() – 移除栈顶元素
top() – 获取栈顶元素
empty() – 返回栈是否为空
来源:力扣(LeetCode)

import java.util.LinkedList;
import java.util.Queue;

//使用队列实现栈
// push(x) -- 元素 x 入栈
//pop() -- 移除栈顶元素
// top() -- 获取栈顶元素
//empty() -- 返回栈是否为空
public class Stack {
    private Queue<Integer>queue;
    Stack(){
        this.queue=new LinkedList<>();
    }
    public void push(int val){
        queue.add(val);
    }
    public int pop(){
        int size=queue.size();
        for(int i=0;i<size-1;i++){
            Integer integer=queue.remove();
            queue.add(integer);
        }
        return queue.remove();
    }
    public int top(){
        int size=queue.size();
        for(int i=0;i<size-1;i++){
            Integer integer=queue.remove();
            queue.add(integer);
        }
        Integer v=queue.remove();
        queue.add(v);
        return v;
    }
    public boolean empty(){
        return queue.isEmpty();
    }
}

力扣 232 用栈实现队列
链接

使用栈实现队列的下列操作:
push(x) – 将一个元素放入队列的尾部。
pop() – 从队列首部移除元素。
peek() – 返回队列首部的元素。
empty() – 返回队列是否为空。
来源:力扣(LeetCode)

import java.util.Deque;
import java.util.LinkedList;
class MyQueue {
/** Initialize your data structure here. */
    private Deque <Integer>s1;
    private Deque<Integer>s2;
public MyQueue() {
   s1=new LinkedList<>();
   s2=new LinkedList<>();
    }
/** Push element x to the back of queue. */
public void push(int x) {
    s2.push(x);
        }
/** Removes the element from in front of queue and returns that element. */
public int pop() {
    if(s1.isEmpty()){
        while(!s2.isEmpty()){
            Integer e = s2.pop();
            s1.push(e);
        }
    }
    return s1.pop();
}
/** Get the front element. */
public int peek() {
    if(s1.isEmpty()){
        while(!s2.isEmpty()){
            Integer e = s2.pop();
            s1.push(e);
        }
    }
    return s1.peek();
}
/** Returns whether the queue is empty. */
public boolean empty() {
        return s1.isEmpty()&&s2.isEmpty();
    }
}

力扣 155.最小栈
链接

设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。
push(x) —— 将元素 x 推入栈中。
pop() —— 删除栈顶的元素。
top() —— 获取栈顶元素。
getMin() —— 检索栈中的最小元素
来源:力扣(LeetCode)

import java.util.Deque;
import java.util.LinkedList;

class MinStack {
//创建两个栈一个存储元素 一个存储最小值
    Deque<Integer>stack1;
    Deque<Integer>stack2;
    MinStack(){
        stack1=new LinkedList<>();
        stack2=new LinkedList<>();
    }
    public void push(int val){
        stack1.push(val);
        //当stack2为空时,将val分别压入stack1和stack2(第一次压入)
        //或者当stack2的栈顶元素大于等于val时压入stack2
        //stack2.peek()>=val该处注意为什么有等号,一开始写的时候没写等号,运行出错了,问题就是压入相同的val值时没有等号就可能出错。
        if(stack2.isEmpty()||stack2.peek()>=val){
            stack2.push(val);
        }
    }
    public void pop(){
        int v=stack1.pop();
        if(v==stack2.peek()){
            stack2.pop();
        }
    }
    public int top(){
        return stack1.peek();
    }
    public int getMin(){
        return stack2.peek();
    }
}

力扣 622.设计循环队列
链接

设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。
循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间。但是使用循环队列,我们能使用这些空间去存储新的值。
你的实现应该支持如下操作:
MyCircularQueue(k): 构造器,设置队列长度为 k 。
Front: 从队首获取元素。如果队列为空,返回 -1 。
Rear: 获取队尾元素。如果队列为空,返回 -1 。
enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。
deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。
isEmpty(): 检查循环队列是否为空。
isFull(): 检查循环队列是否已满。
来源:力扣(LeetCode)

class MyCircularQueue {
//    MyCircularQueue(k): 构造器,设置队列长度为 k 。
//    Front: 从队首获取元素。如果队列为空,返回 -1 。
//    Rear: 获取队尾元素。如果队列为空,返回 -1 。
//    enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。
//    deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。
//    isEmpty(): 检查循环队列是否为空。
//    isFull(): 检查循环队列是否已满。
    private final int []queue;
    private int size;
    private int FrontIndex;
    private int rearIndex;
    /** Initialize your data structure here. Set the size of the queue to be k. */
    public MyCircularQueue(int k) {
        this.queue=new int[k];
        this.size=0;
        this.FrontIndex=0;
        this.rearIndex=0;
    }
    /** Insert an element into the circular queue. Return true if the operation is successful. */
    public boolean enQueue(int value) {
       if(this.size==this.queue.length){
           return false;
       }
       this.queue[rearIndex]=value;
       this.rearIndex++;
       size++;
       if(this.rearIndex==this.queue.length){
           this.rearIndex=0;
       }
        return true;
    }
    /** Delete an element from the circular queue. Return true if the operation is successful. */
    public boolean deQueue() {
        if(this.size==0){
            return false;
        }
        size--;
        this.FrontIndex++;
        if(FrontIndex==this.queue.length){
            FrontIndex=0;
        }

       return true;
    }
    /** Get the front item from the queue. */
    public int Front() {
        if(size==0){
            return -1;
        }
        return this.queue[FrontIndex];
    }
    /** Get the last item from the queue. */
    public int Rear() {
        if(size==0){
            return -1;
        }
        int index=this.rearIndex-1;
        if(index==-1){
            index=this.queue.length-1;
        }
        return this.queue[index];
    }
    /** Checks whether the circular queue is empty or not. */
    public boolean isEmpty() {
        return this.size==0;
    }
    /** Checks whether the circular queue is full or not. */
    public boolean isFull() {
        return this.size==this.queue.length;
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值