牛客网剑指offer-队列&栈(java实现)

一、JZ9 用两个栈实现队列(简单)

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() {
        if(stack2.isEmpty()) {
            while(!stack1.isEmpty()) {
                stack2.push(stack1.pop());
            }
        }
        if(stack2.isEmpty()) {
            return 0;
        } else {
            return stack2.pop();
        }
       
    }
}

二、JZ30 包含min函数的栈(简单)

1、获取栈顶方法时就取出一个值获取到再放进去,获取最小值就使用一个辅助ArrayList记录栈中的值,调用min方法时就进行遍历比较取最小值

import java.util.Stack;
import java.util.ArrayList;
public class Solution {
    Stack<Integer> stack = new Stack<>();
    ArrayList<Integer> list = new ArrayList<>();
    
    public void push(int node) {
        stack.push(node);
        list.add(node);
    }
    
    public void pop() {
        stack.pop();
        list.remove(list.size() -1);
    }
    
    public int top() {
        return stack.peek();
    }
    
    public int min() {
        int min = list.get(0);
        for(int node: list) {
            if(node < min) {
                min = node;
            }
        }
        return min;
    }
}

2、使用辅助栈

import java.util.Stack;

public class Solution {
    //用于栈的push 与 pop
    Stack<Integer> s1 = new Stack<Integer>(); 
    //用于存储最小min
    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();
    }
}

三、JZ31 栈的压入、弹出序列(中等)

1、创建一个栈,通过循环去判断栈顶元素是否等于当前循环中出栈的元素,不等的时候一直入栈入栈数组中的数据,最后判断该栈是否全部数据出栈完即栈是否为空。

import java.util.ArrayList;
import java.util.Stack;
public class Solution {
    public boolean IsPopOrder(int [] pushA,int [] popA) {
        Stack<Integer> stack = new Stack<>();
        int n =popA.length;
        int j = 0;
        for(int i=0;i<n;i++) {
            while(j<n && (stack.isEmpty() || stack.peek() != popA[i])) {
                stack.push(pushA[j]);
                j++;
            }
            if(stack.peek() == popA[i]) {
                stack.pop();
            }
        }
        return stack.isEmpty();
    }
}

四、JZ73 翻转单词序列(简单)

1、先将字符串通过split(" ")分割加入栈,然后再全部出栈拼成一个新的字符串

import java.util.Stack;
public class Solution {
    public String ReverseSentence(String str) {
        Stack<String> stack = new Stack<>();
        for(String item: str.split(" ")) {
            stack.push(item);
        }
        StringBuilder builder = new StringBuilder();
        while(!stack.isEmpty()) {
             builder.append(stack.pop() + " ");   
        }
        return builder.toString().trim();
    }
}

五、JZ59 滑动窗口的最大值(较难)

1、暴力法,直接使用双重遍历,用ArrayList装每个窗口对应的最大值并最终返回

import java.util.*;
public class Solution {
    public ArrayList<Integer> maxInWindows(int [] num, int size) {
        ArrayList<Integer> result = new ArrayList<>();
        if(num.length > 0 && size > 0) {
            for(int i=0;i < num.length - size + 1;i++) {
                    int temp = num[i];
                    for(int j=i;j < (i+size);j++) {
                        if(num[j] > temp) temp = num[j];
                    }
                    result.add(temp);
                }
        }
        return result;
    }
}

2、使用双向队列:step 1:维护一个双向队列,用来存储数列的下标。step 2:首先检查窗口大小与数组大小。step 3:先遍历第一个窗口,如果即将进入队列的下标的值大于队列后方的值,依次将小于的值拿出来去掉,再加入,保证队列是递增序。step 4:遍历后续窗口,每次取出队首就是最大值,如果某个下标已经过了窗口,则从队列前方将其弹出。step 5:对于之后的窗口,重复step 3,直到数组结束。

import java.util.*;
public class Solution {
    public ArrayList<Integer> maxInWindows(int [] num, int size) {
        ArrayList<Integer> res = new ArrayList<Integer>();
        //窗口大于数组长度的时候,返回空
        if(size <= num.length && size != 0){
            //双向队列
            ArrayDeque <Integer> dq = new ArrayDeque<Integer>();  
            //先遍历一个窗口
            for(int i = 0; i < size; i++){
                //去掉比自己先进队列的小于自己的值
                while(!dq.isEmpty() && num[dq.peekLast()] < num[i])
                     dq.pollLast();
                dq.add(i);
            }
            //遍历后续数组元素
            for(int i = size; i < num.length; i++){
                //取窗口内的最大值
                res.add(num[dq.peekFirst()]);
                while(!dq.isEmpty() && dq.peekFirst() < (i - size + 1))
                    //弹出窗口移走后的值
                    dq.pollFirst(); 
                //加入新的值前,去掉比自己先进队列的小于自己的值
                while(!dq.isEmpty() && num[dq.peekLast()] < num[i])
                    dq.pollLast();
                dq.add(i);
            }
            res.add(num[dq.pollFirst()]);
        }     
        return res;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值