算法(Java)——栈、队列、堆

在刷算法题中,栈是一种常用的数据结构。下面介绍一些Java中栈的常用的一些方法以及力扣刷题中用到栈的一些题目。

Java Stack类,栈是Vector的一个子类,实现后进先出的栈。

Stack stackA = new Stack();

使用Stack类,由于Stack继承了Vector接口,而Vector底层是一个Object[]数组,那么就要考虑空间扩容和移位的问题,造成速度较慢,可以使用LinkedList来做Stack的容器。

1.栈的函数

Stack<Integer> stack = new Stack<Integer>();//建栈
stack.push(Element);//进栈
stack.pop();//出栈
stack.peek();//取栈顶值(不出栈)
stack.isEmpty();//判断栈是否为空

2.力扣关于栈的题

1)剑指offer09:用两个栈实现队列

题目:用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )

解题思路:用两个栈,一个栈将输入的数存入栈中,再出栈存到另一个栈中,再出栈的时候就实现了队列的先进先出。

算法代码

class CQueue {
    private Stack StackA;
    private Stack StackB;
    public CQueue() {  //创建栈
        StackA = new Stack();
        StackB = new Stack();
    }    
    public void appendTail(int value) { //入队,进栈
        StackA.push(value);
    }    
    public int deleteHead() {
        if(StackB.empty()){ 
            while(!StackA.empty()){ //将栈A中的数都存到栈B中
                StackB.push(StackA.pop());
            }
        }
        if(StackB.empty()) return -1;
        else return (int)StackB.pop();
    }
}
2)剑指offer31:栈的压入,弹出序列

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

解题思路:辅助栈,判断栈顶元素与输出序列是否相同,相同则出栈,最后判断栈是否为空。

算法代码

class Solution {
    public boolean validateStackSequences(int[] pushed, int[] popped) {
        Stack<Integer> stackA = new Stack();
        int in=0;
        for(int i=0;i<pushed.length;i++){
            stackA.push(pushed[i]);  //进栈
            while(!stackA.isEmpty() && stackA.peek()==popped[in]){ 
                //栈顶元素等于出栈序列元素,出栈
                stackA.pop();
                in++;
            }
        }
        return stackA.isEmpty();//根据栈是否为空,判断
    }
}
3)剑指offer30:包含min函数的栈。

题目:定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)。

解题思路:建立两个辅助栈。

  1. 辅助栈A:用于存储所有元素,保证入栈push()函数、出栈pop()函数,获取栈顶top()函数的正常逻辑。
  2. 辅助栈B:存储栈A中所有非严格降序的元素,则栈A中的最小元素始终对应栈B的栈顶元素。

算法代码

class MinStack {

    Stack<Integer> stackA, stackB;
    public MinStack() {
        stackA = new Stack<>();
        stackB = new Stack<>();
    }
    
    public void push(int x) {
        stackA.add(x);
        if(stackB.empty()||stackB.peek()>=x)
            stackB.add(x);
    }
    
    public void pop() {
        if(stackA.pop().equals(stackB.peek()))  //比较的同时,先执行stackA.pop()
            stackB.pop();
    }
    
    public int top() {
        return stackA.peek();
    }
    
    public int min() {
        return stackB.peek();
    }
}

队列

LinkedList类实现了Queue接口,因此我们可以把LinkedList当成Queue来用。

Queue<String> queue = new LinkedList<String>();

1.队列的函数

添加:queue.offer() queue.add()
删除队列第一个元素:queue.poll()返回null queue.remove()返回异常
查询队列头部元素:peek()返回null element()返回异常

2.力扣关于队列的题

待补充

堆主要介绍PriorityQueue实现的堆。

PriorityQueue,即优先队列。优先队列的作用是能保证每次取出的元素都是队列中权值最小的。堆保证每次插入都排好序。

Java中PriorityQueue默认是小顶堆,可以通过传入自定义的Comparator函数来实现大顶堆。

PriorityQueue<Integer> queue = new PriorityQueue<Integer>(new Comparator<Integer>(){
            public int compare(Integer n1, Integer n2){
                return n2-n1;
            }
        });

1.优先队列实现的堆的函数

创建:PriorityQueue<Integer> queue = new PriorityQueue<Integer>(new Comparator<Integer>()
add()offer() 向优先队列中插入元素
element()peek() 获取但不删除队首元素
remove()poll() 获取并删除队首元素

2.力扣关于堆的题

1)剑指offer40:最小的k个数

题目:输入整数数组 arr ,找出其中最小的 k 个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。

解题思路:使用大顶堆,先将前k个元素加入大顶堆,然后遍历其余元素,若小于堆顶,则加入堆,最后输出堆。

算法代码

class Solution {
    public int[] getLeastNumbers(int[] arr, int k) {
        int[] res = new int[k];
        if(k==0) return res;
        //将小顶堆改为大顶堆,通过comparator函数
        PriorityQueue<Integer> queue = new PriorityQueue<Integer>(new Comparator<Integer>(){
            public int compare(Integer n1, Integer n2){
                return n2-n1;
            }
        });
        for(int i=0;i<k;i++)  queue.offer(arr[i]); //将数组前k个元素加入大顶堆
        for(int i=k;i<arr.length;i++){ //遍历其余元素,若小于堆顶,则加入堆
            if(queue.peek()>arr[i]){
                queue.poll();
                queue.offer(arr[i]);
            }
        }
        for(int i=0;i<k;i++) res[i]=queue.poll(); //将遍历完的大顶堆中元素存入数组
        return res;
    }
}

你可能感兴趣的:(算法分析,算法,数据结构,栈,队列,java)