【算法方法总结·六】栈队列堆的一些技巧和注意事项

【算法方法总结·六】栈队列堆的一些技巧和注意事项


【栈队列堆】

【栈】

可以用 Stack,但是一般用 Deque,比较方便

Stack

Stack<Integer> stack = new Stack<>()

stack.pop() // 出栈,并返回出栈元素
stack.push(x) // 把x入栈
stack.peek() // 返回栈顶元素
stack.isEmpty() // 是否为空
stack.isFull() // 是否满了
stack.length // 长度

Deque

也支持 栈操作

请添加图片描述

// 双端队列
Deque<Integer> deque = new Linkedlist<>()

// 也支持栈操作
pop()removeFirst()
push()addFirst()
peek()peekFirst()
poll()pollFirst()
offer(x)offerLast(x)

【单调栈】

  • 通常是一维数组,要寻找任一个元素的右边或者左边第一个比自己大或者小的元素的位置,此时我们就要想到可以用单调栈了
  • 单调栈的本质是空间换时间,更直白来说,就是用一个栈来记录我们遍历过的元素
  • 顺序的描述为 从栈头到栈底的顺序
    请添加图片描述
    例如 接雨水问题
// 用接雨水问题来分析
class Solution {
    public int trap(int[] height) {
        Deque<Integer> st = new LinkedList<>(); // 存下标
        int len = height.length;
        st.push(0); // 第一个元素的下标 0 入栈
        int res = 0;
        for (int i = 1; i < len; i++) {
        	// 单调栈的栈顶元素一定是最小的
            if (height[i] < height[st.peek()]) {
                st.push(i);
            } else if (height[i] == height[st.peek()]) { // 顶==添加,用右边的
                st.pop(); // 左边的弹出
                st.push(i);
            } else { // 顶 < 添加,开始计算并出栈
                while (!st.isEmpty() && height[i] > height[st.peek()]) {
                    int mid = st.pop(); // 凹槽
                    if (!st.isEmpty()) {
                        int left = st.peek();
                        // right=i
                        // min(左,右)- 凹槽
                        int h = Math.min(height[i], height[left]) - height[mid];
                        int w = i - left - 1;
                        int hold = h * w;// 当前行接雨量
                        res += hold;
                    }
                }
                st.push(i);
            }
        }
        return res;
    }
}

【队列堆】

普通队列

Queue 是个接口,在实例化时必须实例化 LinkedList 的对象,因为 LinkedList 实现了 Queue 接口

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

queue.size() // 长度
queue.peek() / queue.element() // 返回队头元素
queue.poll() / queue.remove() // 出队,并返回出队元素
queue.offer(x) / queue.add(x) // 入队
queue.isEmpty() //是否为空

双端队列

Deque 是一个接口,使用时必须创建 LinkedList 的对象(一般不用 ArrayDeque),它也支持 Queue的方法

Deque<Integer> stack = new ArrayDeque<>();//双端队列的线性实现
Deque<Integer> queue = new LinkedList<>();//双端队列的链式实现

// 其方法相对于 Queue 多了 -First 及 -Last
addFirst() / offerFirst()
removeFirst() / pollFirst()
getFirst() / peekFirst()

// 也支持栈操作
pop()removeFirst()
push()addFirst()
peek()peekFirst()
poll()pollFirst()
offer(x)offerLast(x)

优先队列【即为堆】

PriorityQueue 默认情况下是小根堆 —— 即每次获取到的元素都是最小的元素

// 默认为小根堆
PriorityQueue<Integer> q1 = new PriorityQueue<>();

3 种 大根堆 自定义方式

方法一
// 大根堆要自己定义
// 定义方式(1)
class IntCmp implements Comparator<Integer>{
    @Override
    public int compare(Integer o1, Integer o2) {
        return o2 - o1;
    }
}
PriorityQueue<Integer> p = new PriorityQueue<>(new IntCmp());
方法二
// 定义方式(2)
PriorityQueue<int[]> queue = new PriorityQueue<int[]>(new Comparator<int[]>() {
	public int compare(int[] o1, int[] o2) {
		return o2[1] - o1[1];
	}
});
方法三:Lambda 表达式 (推荐)
// 定义方式(3) Lambda表达式--推荐
PriorityQueue<int[]> p = new PriorityQueue<>((pair1, pair2) -> pair2[1] - pair1[1]);
堆操作
size() // 有效元素个数
offer() / add() // 插入
peek() // 获取优先级最高的元素
poll() / remove() // 移除优先级最高的元素
clear() // 清空
isEmpty() // 是否为空

相关力扣题

232.用栈实现队列 简单

150. 逆波兰表达式求值

239. 滑动窗口最大值 困难

347.前 K 个高频元素

20.有效的括号 简单

155.最小栈

394.字符串解码

739.每日温度

84.柱状图中最大的矩形 困难

215.数组中的第k个最大元素

295.数据流的中位数 困难

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值