剑指offer :栈和队列类题目汇总

            基本操作:https://www.cnblogs.com/whsa/p/4272717.html

栈----先进后出

 push(E item)       把项压入堆栈顶部。   

 pop()          移除堆栈顶部的对象,并作为此函数的值返回该对象。   

peek()        查看堆栈顶部的对象,但不从堆栈中移除它。   

boolean empty()           测试堆栈是否为空。    

int search(Object o)        返回对象在堆栈中的位置,以 1 为基数。  

 

队列----先进先出:

1.往队列中添加元素: add()、put()、offer()

 2.从队列中取出或者删除元素: remove()、element()、peek()、 pool()、take()

      offer()方法往队列添加元素如果队列已满直接返回false,队列未满则直接插入并返回true;

      add()方法是对offer()方法的简单封装.如果队列已满,抛出异常new IllegalStateException("Queue full");

       put()方法往队列里插入元素,如果队列已经满,则会一直等待直到队列为空插入新元素,或者线程被中断抛出异常.

       remove()方法直接删除队头的元素:

       peek()方法直接取出队头的元素,并不删除.

       element()方法对peek方法进行简单封装,如果队头元素存在则取出并不删除,如果不存在抛出异常NoSuchElementException()

       pool()方法取出并删除队头的元素,当队列为空,返回null;

       take()方法取出并删除队头的元素,当队列为空,则会一直等待直到队列有新元素可以取出,或者线程被中断抛出异常

 

9.用两个栈实现队列:

          用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。

         解题思路:利用栈实现队列,重点在于删除一个元素,如果当第二个栈为空,则将第一个栈的元素全部弹出到第二个栈,当第二个栈不为空时,直接弹出第二个栈的栈顶元素即可。

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.size()<=0){
           while(stack1.size()>0)
              stack2.push(stack1.pop());
        }
        return stack2.pop();
    }
}

          相关问题:利用两个队列实现一个栈。重点在于用两个队列实现从栈中删除栈顶元素,当队列1中只有一个元素,直接弹出即可,如果队列的长度大于1,则将元素从队首依次弹出,弹入到队2中,直至队1中只有一个元素。

 

30.包含min函数的栈:

          定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数。

          解题思路:如果只设置一个变量来保存最小值的话,当最小值弹出栈后则无法再获得最小值,因此,需要设置一个辅助栈,保存每次添加数据后的最小元素,当栈的元素弹出后,辅助栈的元素也要弹出。

import java.util.Stack;
public class Solution {
    Stack<Integer> stack1 = new Stack<Integer>();
    Stack<Integer> stack2 = new Stack<Integer>();
    int minNode = Integer.MAX_VALUE;;
    
    public void push(int node) {
        stack1.push(node);
        if(minNode>node){
            stack2.push(node);
            minNode = node;
        }else 
            stack2.push(minNode);
    }
    
    public void pop() {
        stack1.pop();
        stack2.pop();
    }
    
    public int top() {
        return stack1.peek();
    }
    
    public int min() {
        return stack2.peek();
    }
}

 

31.栈的压入、弹出序列:

         输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)。

          解题思路:建立一个辅助栈,把输入的第一个序列中的数字依次压入辅助栈中,如果栈顶元素和第二个序列的元素相同,弹出栈,否则,接着压入栈中,直到第一个序列的元素全部压入过。最后如果栈为空,则压栈序列和弹出序列为一致,否则不同,输出false。

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

 

59.队列的最大值:

1)滑动窗口的最大值:

         给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{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]}。

         解题思路:将窗口的最后一个值设为初始最大值,依次与窗口内的每一个值进行比较,得到最大值,添加到集合中返回。

import java.util.*;
public class Solution {
    public ArrayList<Integer> maxInWindows(int [] num, int size){
        ArrayList<Integer> result = new  ArrayList<Integer>();
        if(num ==null || size<=0 || num.length==0)
            return result;
        for(int i = size-1;i<num.length ;i++){//第一个窗口外
            int max = num[i];
            for(int j=0;j<size;j++){
                if(max<num[i-j])
                    max = num[i-j];
            }
            result.add(max);
        }
        return result;
    }
}

         先判断当前队列是否为空,如果不空而且当前元素比队列中尾端的元素大,将队列元素的尾端弹出;判断队列头元素(存的是下标)是否还在滑动窗口范围中,不在则把头元素移除;

import java.util.*;
public class Solution {
    public ArrayList<Integer> maxInWindows(int [] num, int size){
        ArrayList<Integer> result = new  ArrayList<Integer>();
        LinkedList<Integer> queue = new LinkedList<Integer>();
        if(num ==null || size<=0 || num.length==0)
            return result;
        for(int i =0;i<num.length ;i++){
            //实现队列中按照从小到大的方式存储,存储下标
            if(queue.size()<=0){
                queue.addLast(i);
            }else{
                if(num[i]<= num[queue.getLast()])
                   queue.addLast(i);
                else{
                    while(queue.size()!=0 && num[i]> num[queue.getLast()])
                        queue.removeLast();
                    queue.addLast(i);
                }
            }
            //判断对头元素的下标是否还在华东窗口范围内
            if(i+1>=size){
                int first = queue.getFirst();
                while ((i - first) > size - 1) {
                    queue.removeFirst();
                    first = queue.getFirst();
                }
               result.add(num[first]);
            }
        }
     return result;
    }
}

      更多滑动窗口相关问题参见我的博客:https://blog.csdn.net/danjuanzi2684/article/details/83344517

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值