Java\Leetcode刷题---栈和队列专题

Java栈和队列专题

引言:栈和队列也是数据结构中常用的数据结构,栈的特点是先进后出(FILO),可以理解为手枪的弹夹,只能在栈顶增加和删除元素;队列的特点是先进先出(FIFO),就是正常的排队,只能在队尾入队,并且只能在队头出队。

1.Java栈理论基础

​ Java中栈在标准库中定义,即java.util.Stack。其继承自Vector类,因此可以视为一个动态数组。

// 创建 
Stack<Integer> stack = new Stack<>();
// 栈顶入栈
stack.push(1);
stack.push(2);
// 栈顶出栈
stack.pop();
// 判空
stack.isEmpty();
// 获取栈顶元素
stack.peek();

2.Java队列理论基础

2.1 普通队列

Java标准库提供了java.util.Queue接口来定义队列的基本操作。Queue接口继承自java.util.Collection接口,并且它有多个实现类,其中最常用的实现类是LinkedList和ArrayDeque。

 // 创建一个队列
Queue<Integer> queue = new LinkedList<>();
// 添加元素到队列尾部
queue.add(10);
queue.add(20);
queue.add(30);
// 从队头删除元素
queue.remove();
// 获取队头元素
queue.peek();

2.2 优先队列

2.2.1 优先队列的定义

​ 优先队列是指每个元素都有优先级,优先级高的在队头,出队时最先出。优先级相同的则按照先入先出原则出队。优先队列可以由数组或列表实现,数组可以实现一个无序的优先队列,即在插入元素时,直接在数组最后插入(复杂度为O(1)),而出队时则需要挨个比较,找到优先级最高的(复杂度为O(n))。链表可以实现一个有序的优先队列,即插入元素时按大小顺序插入(复杂度为O(n)),这样出队时只需要将队头元素出队即可(时间复杂度为O(1))。

​ 然而还有更高效的方法,即通过堆结构来构建优先队列:

首先堆结构(Heap)的定义是:

  • 具备完全二叉树结构(完全二叉树即按照层序编号后,所有节点与对应的满二叉树中的结点编号一致,满二叉树是指所有父节点都有两个子结点,并且所有叶子节点都在同一层)
  • 父节点的值一定大于等于(或小于等于)两个子结点的值,如果大于等于,则称为大顶堆;否则,称为小顶堆。

其次,堆结构的优点有:

  • 由于堆结构是一个完全二叉树,其亲子关系完全可以用编号来表示。即父节点k的两个子结点分别是2k和2k+1,而子结点n对应的父节点的编号为floor(n/2)。基于这个特性,完全二叉树完全可以用一个数组来表示。
  • 对一个满二叉树而言,显然每层的元素个数为1,2,4,8,16,…,事实上,每当元素个数N达到2的幂时,二叉树的高度就会增加1。因此,N个元素的二叉树,其高度为logN。正因如此,在后续进行插入和删除操作时,其时间复杂度将为O(logn)。

基于大顶堆实现的优先队列称为最大优先队列,否则称为最小优先队列。以最小优先队列为例(即顶部元素最小):

​ 当插入元素时,只需将其插入队尾处,然后跟父亲节点比较大小,如果比父亲节点小,就与父亲节点交换位置,并且继续与其当前的父亲节点比较,直到上浮到合适的位置。(可以看到这样纵向的比较,其时间复杂度为O(logN))

​ 在删除元素时,只能删除队头元素,只需把队尾元素复制到队头,然后删除队尾元素(对数组来说,删除队尾就是O(1)),然后让当前的队头元素下沉即可。时间复杂度也为O(logN).

2.2.2 Java 优先队列

​ Java中优先队列由标准库中的PriorityQueue类实现,其是基于小顶堆来实现的,即队头元素对应的值是最小的,因此如果以数字的自然顺序构建PriorityQueue的话,队头元素将是最小的。

// 小顶堆实现的最小优先队列
PriorityQueue<Integer> minPQ = new PriorityQueue<>((o1,o2)->o1-o2);// o1-o2就是自然序(即从小到大)
// 大顶堆实现的最大优先队列
PriorityQueue<Integer> maxPQ = new PriorityQueue<>((o1,o2)->o2-o1);// o2-o1就是逆序(即从大到小)
PriorityQueue<Integer> maxPQ2 = new PriorityQueue<>(Comparator.reverseOrder());// 也可以使用Comparator接口的逆序方法
// 添加元素(加入后元素将自动落入合适的位置)
PQ.add(1);
PQ.add(2);
// 删除元素(队头)
PQ.remove();
// 获取队头元素
PQ.peek();
// 大小
PQ.size();
// 包含某元素
PQ.contains(1)

3.Java栈相关题目

232. 用栈实现队列

225. 用队列实现栈

20. 有效的括号

1047. 删除字符串中的所有相邻重复项

150. 逆波兰表达式求值

4.Java优先队列相关题目

347. 前 K 个高频元素

239. 滑动窗口最大值

你可能感兴趣的:(LeetCode刷题记录,java,leetcode,开发语言)