在刷算法题中,栈是一种常用的数据结构。下面介绍一些Java中栈的常用的一些方法以及力扣刷题中用到栈的一些题目。
Java Stack类,栈是Vector的一个子类,实现后进先出的栈。
Stack stackA = new Stack();
使用Stack类,由于Stack继承了Vector接口,而Vector底层是一个Object[]数组,那么就要考虑空间扩容和移位的问题,造成速度较慢,可以使用LinkedList来做Stack的容器。
Stack<Integer> stack = new Stack<Integer>();//建栈
stack.push(Element);//进栈
stack.pop();//出栈
stack.peek();//取栈顶值(不出栈)
stack.isEmpty();//判断栈是否为空
题目:用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 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();
}
}
题目:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如,序列 {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();//根据栈是否为空,判断
}
}
题目:定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)。
解题思路:建立两个辅助栈。
算法代码:
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>();
添加:queue.offer() queue.add()
删除队列第一个元素:queue.poll()返回null queue.remove()返回异常
查询队列头部元素:peek()返回null element()返回异常
待补充
堆主要介绍PriorityQueue实现的堆。
PriorityQueue,即优先队列。优先队列的作用是能保证每次取出的元素都是队列中权值最小的。堆保证每次插入都排好序。
Java中PriorityQueue默认是小顶堆,可以通过传入自定义的Comparator函数来实现大顶堆。
PriorityQueue<Integer> queue = new PriorityQueue<Integer>(new Comparator<Integer>(){
public int compare(Integer n1, Integer n2){
return n2-n1;
}
});
创建:PriorityQueue<Integer> queue = new PriorityQueue<Integer>(new Comparator<Integer>()
add()和offer() 向优先队列中插入元素
element()和peek() 获取但不删除队首元素
remove()和poll() 获取并删除队首元素
题目:输入整数数组 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;
}
}