牛客编程题--必刷101之堆栈队列篇(上)

CSDN话题挑战赛第1期
活动详情地址:https://marketing.csdn.net/p/bb5081d88a77db8d6ef45bb7b6ef3d7f
参赛话题:Leetcode刷题指南
话题描述:代码能力是一个程序员的基本能力,而除了做项目之外,大家接触到的最常规的提升代码能力的方法基本就是刷题了,因此,加油刷题,冲刺大厂!
创作模板:Leetcode刷题指南


大家好,我是小曾哥,虽然不是首发用户,但是也来参与参与活动,希望能够得到大家都支持,目前牛客刷题已经到了下一个专题(堆、栈、队列),对应题目力扣应该也是可以搜到的!

文章目录

  • 一、用两个栈实现队列
    • 1.题目描述
    • 2.思路:双栈
    • 3. 代码详解
  • 二、包含min函数的栈
    • 1.题目描述
    • 2.思路:辅助栈
    • 3. 代码详解
  • 三、 有效括号序列
    • 1.题目描述
    • 2.思路:辅助栈
    • 3. 代码详解
  • 四、 滑动窗口的最大值
    • 1.题目描述
    • 2.思路:双端队列
    • 3. 代码详解

一、用两个栈实现队列

1.题目描述

用两个栈来实现一个队列,使用n个元素来完成 n 次在队列尾部插入整数(push)和n次在队列头部删除整数(pop)的功能。 队列中的元素为int类型。保证操作合法,即保证pop操作时队列内已有元素。

输入:[“PSH1”,“PSH2”,“POP”,“POP”]
返回值:1,2
说明:“PSH1”:代表将1插入队列尾部
“PSH2”:代表将2插入队列尾部
"POP“:代表删除一个元素,先进先出=>返回1
"POP“:代表删除一个元素,先进先出=>返回2

2.思路:双栈

题目已经描述,将用两个栈来实现队列
栈是后进先出,队列是先进先出,想要用栈实现队列,需要把一个栈中的元素挨个pop()出来,再push到另一个栈中。
牛客编程题--必刷101之堆栈队列篇(上)_第1张图片
上图中,我们将栈a中的数据全部pop()出来,再放入栈b中,经过这么一番操作后,栈b中的元素顺序就变成先进先出的顺序了,所以栈b中的顺序跟队列顺序一样了。

push函数实现如下:
牛客编程题--必刷101之堆栈队列篇(上)_第2张图片
分三步操作(维持栈b中的顺序是先进先出的顺序):
将栈b中的内容倒腾到栈a中
将新元素插入栈a中
再将栈a中的所有数据倒腾到栈b中

3. 代码详解

都注解了对应的注释,是Java的两种实现方式

方法1
import java.util.Stack;

public class Solution {
    Stack<Integer> stack1 = new Stack<Integer>();
    Stack<Integer> stack2 = new Stack<Integer>();
    
    public void push(int node) {
        stack1.push(node);
    }
    
    public int pop() {
        // 如果栈2为空,栈1不为空,则将栈1全部元素push到栈2中
        if(stack2.size()<=0){
            while(stack1.size()!=0){
                 stack2.push(stack1.pop());
            } 
        }
        // 如果栈2不为空,则直接pop元素即可
        int res = stack2.pop();
        return res;
    }
}

方法2
public class Solution {
    Stack<Integer> stack1 = new Stack<Integer>();
    Stack<Integer> stack2 = new Stack<Integer>();
    
    public void push(int node) {
        stack1.push(node);
    }
    
    public int pop() {
        // 将栈1内容放入栈2中
        while(!stack1.isEmpty()){
            stack2.push(stack1.pop());
        }
        // 将栈2栈顶元素,为队首
        int res = stack2.pop();
        // 将栈2元素放入栈1
        while(!stack2.isEmpty())
            stack1.push(stack2.pop());
        return res;
    }
}

二、包含min函数的栈

1.题目描述

定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的 min 函数,输入操作时保证 pop、top 和 min 函数操作时,栈中一定有元素。

此栈包含的方法有:
push(value):将value压入栈中
pop():弹出栈顶元素
top():获取栈顶元素
min():获取栈中最小元素

输入: [“PSH-1”,“PSH2”,“MIN”,“TOP”,“POP”,“PSH1”,“TOP”,“MIN”]
输出: -1,2,1,-1
解析:
"PSH-1"表示将-1压入栈中,栈中元素为-1
"PSH2"表示将2压入栈中,栈中元素为2,-1
“MIN”表示获取此时栈中最小元素==>返回-1
"TOP"表示获取栈顶元素==>返回2
"POP"表示弹出栈顶元素,弹出2,栈中元素为-1
"PSH1"表示将1压入栈中,栈中元素为1,-1
"TOP"表示获取栈顶元素==>返回1
“MIN”表示获取此时栈中最小元素==>返回-1

2.思路:辅助栈

牛客编程题--必刷101之堆栈队列篇(上)_第3张图片
push操作就如图片上操作。
pop操作直接对应弹出就好了。
top操作就返回normal的栈顶
min操作就返回minval的栈顶

Stack.peek()
peek()函数返回栈顶的元素,但不弹出该栈顶元素。
Stack.pop()
pop()函数返回栈顶的元素,并且将该栈顶元素出栈。

3. 代码详解

public class Solution {
    
    // 用于栈道push和pop
    public Stack<Integer> s1 = new Stack<Integer>();
    // 用于存取栈的最小值
    public Stack<Integer> s2 = new Stack<Integer>();
    
    public void push(int node) {
        s1.push(node);
        // 新元素较小,则入栈
        if(s2.isEmpty()) s2.push(node);
        else{
            if(node <= s2.peek()){
                s2.push(node);
            }
            else{
                s2.push(s2.peek());
            }
        }
        
    }
    
    public void pop() {
        s1.pop();
        s2.pop();
    }
    
    public int top() {
        return s1.peek();
    }
    
    public int min() {
        return s2.peek();
    }
}

精简版

import java.util.Stack;

public class Solution {
    
    // 用于栈道push和pop
    public Stack<Integer> s1 = new Stack<Integer>();
    // 用于存取栈的最小值
    public Stack<Integer> s2 = new Stack<Integer>();
    
    public void push(int node) {
        s1.push(node);
        // 新元素较小,则入栈
        if(s2.isEmpty() || s2.peek()> node) s2.push(node);
        else{
            s2.push(s2.peek());
        }
        
        
    }
    
    public void pop() {
        s1.pop();
        s2.pop();
    }
    
    public int top() {
        return s1.peek();
    }
    
    public int min() {
        return s2.peek();
    }
}

三、 有效括号序列

1.题目描述

给出一个仅包含字符’(‘,’)‘,’{‘,’}‘,’[‘和’]',的字符串,判断给出的字符串是否是合法的括号序列括号必须以正确的顺序关闭,"()“和”()[]{}“都是合法的括号序列,但”(]“和”([)]"不合法。

输入:“()[]{}”
返回值:true
输入:“([)]”
返回值:false

2.思路:辅助栈

每次遇到’(‘,’{‘,’[‘这三种字符的时候,将字符入栈stk;而每次遇到’)‘,’}‘,’]‘这三种字符的时候则让对应的匹配字符出栈。具体规则如下:
1)引入辅助栈stk,遍历字符串,每次遇到’(‘,’{‘,’[‘字符的时候将字符入栈stk
2)当遇到’)‘,’}‘,’]'字符的时候,则检查栈是否空,且顶元素是否为匹配元素(如{和}匹配等),如果栈空或者栈顶元素不为匹配元素则括号序列不合法
3)当栈非空,且栈顶元素为匹配元素,则栈顶元素出栈。
4)循环匹配字符串,直到每次字符处理完
5)检查栈stk是否为空,栈为空则序列合法,否则不合法(当括号以正确顺序关闭时则最后的栈为空)
牛客编程题--必刷101之堆栈队列篇(上)_第4张图片

3. 代码详解

public boolean isValid (String s) {
        // 辅助栈
        Stack<Character> st = new Stack<>();
        // 遍历字符串
        for(int i =0 ;i < s.length();i++){
            if(s.charAt(i) == '(')
                st.push(')');
            else if(s.charAt(i) == '[')
                st.push(']');
            else if(s.charAt(i) == '{')
                st.push('}');
            else if(st.isEmpty() || st.pop() != s.charAt(i))
                return false;
        }
        
        return st.isEmpty();
    }

四、 滑动窗口的最大值

1.题目描述

给定一个长度为 n 的数组 nums 和滑动窗口的大小 size ,找出所有滑动窗口里数值的最大值。

例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}; 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。

输入:[2,3,4,2,6,2,5,1],3
返回值:[4,4,6,6,6,5]
输入:[9,10,9,-7,-3,8,2,-6],5
返回值:[10,10,9,8]

2.思路:双端队列

用一个双端队列,队列第一个位置保存当前窗口的最大值,当窗口滑动一次
1.判断当前最大值是否过期
2.新增加的值从队尾开始比较,把所有比他小的值丢掉

牛客编程题--必刷101之堆栈队列篇(上)_第5张图片

3. 代码详解

import java.util.*;
public class Solution {
    public ArrayList<Integer> maxInWindows(int [] num, int size) {
        ArrayList<Integer> res = new ArrayList<>();
        // 窗口大于数组长度的时候,返回空
        if(size<= num.length && size !=0){
            // 定义双向队列
            ArrayDeque<Integer> q = new ArrayDeque<Integer>();
            // 先遍历窗口
            int begin;
            for(int i =0; i< num.length; i++){
                begin = i - size + 1;
                if(q.isEmpty())
                    q.add(i);
                else if(begin > q.peekFirst())
                    q.pollFirst();
                // 去掉比自己先进队列的小于自己的值
                while(!q.isEmpty() && num[q.peekLast()] < num[i])
                    q.pollLast();
                q.add(i);
                if(begin >=0)
                    res.add(num[q.peekFirst()]);
            }   
        }
        return res;
    }
}

CSDN话题挑战赛第1期
活动详情地址
:https://marketing.csdn.net/p/bb5081d88a77db8d6ef45bb7b6ef3d7f

你可能感兴趣的:(leetcode,java,算法,堆,栈)