栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

【Java—(18) 栈和队列,以及Leetcode相关问题,附源码】

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【Java—(18) 栈和队列,以及Leetcode相关问题,附源码】

(点击跳转即可哦)

java学习专栏

LeetCode刷题专栏


文章目录
  • 栈和队列
    • 栈的常见问题
    • Leetcode-20
    • Leetcode-155
  • 队列
    • Leetcode-225
    • Leetcode-232
    • Leetcode-622
    • 双端队列

栈和队列

线性表:一次保存单个同类型元素,多个元素之间逻辑上连续

数组,链表,栈,队列,字符串(内部就是char[])

栈和队列 其实是操作受限的线性表。“栈和队列”只能在一端插入元素 和删除元素。

之前的数组也罢,链表也罢,既可以在头部插入和删除,也能在尾部插入和删除,甚至可以在任意位置插入和删除。


栈:是一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。

进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。

栈中的数据元素遵守先进后出LIFO(Last In First Out)的原则。

压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。

出栈:栈的删除操作叫做出栈。出数据在栈顶。

就像一个米缸一样,先放入的大米在最底部,最后放入的大米在最上方,要想取出大米,只能从上往下一层一层的往出取。


栈的对象

Stack stack = new Stack<>();

栈的核心操作:

E push(E item) 压栈

E pop() 出栈

E peek() 查看栈顶元素

boolean isEmpty() 判断栈是否为空


栈的实现

1 基于数组实现的栈 - 顺序栈

2 基于链表实现的栈- 链式栈

//基于数组实现的栈
package stacktest.mystack_array;

import java.util.ArrayList;

import java.util.EmptyStackException;
import java.util.List;

public class Mystack {
   private int size;
   List stack = new ArrayList<>();

   
   public E push(E val){
       stack.add(val);
       size++;
       return val;
   }

   
   public E pop(){
       if(isEmpty()){
           throw new EmptyStackException();
       }
       E val = stack.remove(size-1);
       size--;
       return val;
   }

   
   public boolean isEmpty() {
       return size == 0;
   }

   
   public E peek(){
       if(isEmpty()){
           throw new EmptyStackException();
       }
       return stack.get(size-1);
   }

   @Override
   public String toString() {
       return stack.toString();
   }
}


栈的常见问题 Leetcode-20

有效的括号:

思路:

遇到左括号直接入栈,遇到不是左括号,出栈与这个右括号进行配对,若不是,直接返回false,若是,继续向后扫描。

还需要注意,若扫描到终点,此时栈内还有元素,则说明左括号比右括号多,返回false,若栈内已经为空,则还没有扫描到终点,说明右括号比左括号多,返回false.

import java.util.Stack;


public class Leetcode_20 {
    public boolean isValid(String s) {
        //若只有一个括号,返回false
        if (s.length() == 1) {
            return false;
        }
        Stack stack = new Stack<>();
        //循环扫描字符串
        for (int i = 0; i < s.length(); i++) {
            //读取单个字符
            char str = s.charAt(i);
            //遇到左括号就入栈
            if (str == '(' || str == '[' || str == '{') {
                stack.push(str);
            } else { //遇到了右括号
                //栈为空的情况
                if (stack.isEmpty()) {
                    return false;
                }
                //栈顶元素出栈
                char ch = stack.pop();
                //与右括号进行匹配
                if (str == ')' && ch != '(') {
                    return false;
                }
                if (str == ']' && ch != '[') {
                    return false;
                }
                if (str == '}' && ch != '{') {
                    return false;
                }
            }
        }
        //扫描结束后,若此时栈为空,返回true,栈不为空,返回false
        return stack.isEmpty();
    }
    //测试用例
    public static void main (String[]args){
        Leetcode_20 leetcode_20 = new Leetcode_20();
        String s = "()[]{}";
        System.out.println(leetcode_20.isValid(s));
    }
}

Leetcode-155

最小栈问题:

思路:

采用双栈的思路,一个栈正常保存元素,

另一个栈也保存元素,栈为空,直接入栈,栈不为空,在保存时判断,val 和栈顶元素的大小,val小,直接入栈,栈顶元素小,读取栈顶元素进行入栈。这样栈顶保存的永远是当前栈内最小的元素。

package stacktest.leetcode;

import java.util.Stack;


public class Leetcode_155 {
    Stack s1 = new Stack<>();
    Stack s2 = new Stack<>();
    public void push(int val) {
        if(s1.isEmpty()){
            s1.push(val);
            s2.push(val);
            return;
        }
        s1.push(val);
        if(val <= s2.peek()){
            s2.push(val);
        }else {
            s2.push(s2.peek());
        }
    }
    public void pop() {
        s1.pop();
        s2.pop();
    }

    public int top() {
        return s1.peek();
    }

    public int getMin() {
        return s2.peek();
    }
}

队列

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out)

入队列:进行插入操作的一端称为队尾(Tail/Rear)

出队列:进行删除操作的一端称为队头 (Head/Front)


JDK内置的队列

Queue queue = new LinkedLst<>();

出队操作只能在队列的头部进行,若采用数组的方案,每次出队一个元素,都要搬移剩下的索引元素向前移动一个单位。

所以此时采用链表的方案更加适合对列的结构。

poll 出队列:删除头节点

offer 入队:尾插

peek 查看队首元素:头节点

package queue.myqueue;

import java.util.NoSuchElementException;

public class MyQueue {
    private Node head;
    private Node tail;
    private int size;

    
    public void offer(E val){
        Node node = new Node<>(val);

        if(isEmpty()){
            tail = node;
            head = node;
            size++;
            return;
        }
        tail.next = node;
        tail = tail.next;
        size++;
    }

    
    public E poll(){
        if(isEmpty()){
            throw new NoSuchElementException("队列为空~~");
        }
        size--;
        Node node = head;
        head = head.next;
        node.next = null;
        return node.val;
    }
    
    public E peek(){
        if(isEmpty()){
            throw new NoSuchElementException("队列为空~~");
        }
        return head.val;
    }

    
    public boolean isEmpty(){
        return size == 0;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("h [");
        for (Node x= head; x != null;x = x.next) {
            sb.append(x.val);
            if (x.next != null){
                sb.append(",");
            }
        }
        sb.append("] t");

        return sb.toString();
    }
}
class Node {
    E val;
    Node next;
    public Node(E val) {
        this.val = val;
    }
}

Leetcode-225

用队列实现栈:

使用两个队列实现一个栈

package stacktest.leetcode;

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


public class Leetcode_225 {
    //使用两个队列
    Queue q1 = new LinkedList<>();
    Queue q2 = new LinkedList<>();
    public void push(int x) {
        q2.offer(x);
        while (!q1.isEmpty()){
            q2.offer(q1.poll());
        }
        Queue tmep = q1;
        q1 = q2;
        q2 = tmep;
    }

    public int pop() {
        return q1.poll();
    }

    public int top() {
        return q1.peek();
    }

    public boolean empty() {
        return q1.isEmpty();
    }
}
    //使用一个队列,实现栈
    Queue queue = new LinkedList<>();
    public void push(int x) {
        queue.offer(x);
        while (queue.peek() != x) {
            queue.offer(queue.poll());
        }
    }

    public int pop () {
        return queue.poll();
    }

    public int top () {
        return queue.peek();
    }

    public boolean empty () {
        return queue.isEmpty();
    }
}


Leetcode-232

用栈实现队列:

import java.util.Stack;


public class Leetcode_232 {
    Stack s1 = new Stack<>();
    Stack s2 = new Stack<>();

    public void push(int x) {
        if(s1.isEmpty()){
            s1.push(x);
            return;
        }
        while(!s1.isEmpty()){
            s2.push(s1.pop());
        }
        s1.push(x);
        while(!s2.isEmpty()){
            s1.push(s2.pop());
        }
    }

    public int pop() {
        return s1.pop();
    }

    public int peek() {
        return s1.peek();
    }

    public boolean empty() {
        return s1.isEmpty();
    }
}

Leetcode-622

循环队列:

package stacktest.leetcode;


public class Leetcode_622 {
    Integer[] data;
    private int head;
    private int tail;
    public Leetcode_622(int k) { //MyCircularQueue
        data = new Integer[k+1];
    }
    public boolean enQueue(int value) {
        if(isFull()){
            return false;
        }
        data[tail] = value;
        tail = (tail+1)% data.length;
        return true;
    }

    public boolean deQueue() {
        if(isEmpty()){
            return false;
        }
        head = (head+1)%data.length;
        return true;
    }

    public int Front() {
        if(isEmpty()){
            return -1;
        }
        return data[head];
    }

    public int Rear() {
        if (isEmpty()){
            return -1;
        }
        Integer index = tail == 0 ? data.length-1 : tail-1;
        return data[index];
    }

    public boolean isEmpty() {
        return head == tail;
    }

    public boolean isFull() {
//        if((tail+1)%data.length == head){
//            return true;
//        }
//        return false;
        return (tail + 1) % data.length == head;
    }
}

双端队列

双端队列: Deque是Queue的子接口,这个队列既可以尾插,头出,也可以头插,尾出。

以后无论是需要使用栈还是接口,统一使用双端队列接口,不推荐使用Stack这个类,双端队列的一个常用子类就是LinkedList


需要一个栈

Qeque stack = new LinkedList<>();
stack.push(1);
stack.push(2);
stack.push(3);
System.out.println(stack.pop());

需要一个队列

Qeque queue = new LinkedList<>();
queue.offer(1);
queue.offer(2);
queue.offer(3);
System.out.println(queue.pop());

要是对大家有所帮助的话,请帮我点个赞吧。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/892077.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号