AlgoMooc

双端队列

9 / 28基础内容

数据结构动画

双端队列

加载中
正在加载动画引擎...

本课导读

双端队列是普通队列的升级版:头和尾两端都能进、也都能出,所以它既能当栈、又能当队列。

你将学到
  • 四种操作:头尾各能进出,都 O(1)
  • 和栈(一头进出)、队列(一进一出)的区别
  • 滑动窗口最大值等经典应用

双端队列是什么

想象一个队伍,你既可以从队头离开,也可以从队尾离开;新来的人既可以从队尾加入,也可以从队头插队——这就是双端队列(Deque,读作“deck”)。它允许在两端进行插入和删除操作,比普通队列更灵活。

四种基本操作与复杂度

操作描述时间复杂度
addFirst在队头插入元素O(1)
addLast在队尾插入元素O(1)
removeFirst删除队头元素O(1)
removeLast删除队尾元素O(1)

所有操作都是常数时间,因为双端队列只操作两端,不涉及中间元素。

和栈/队列的关系

双端队列可以“兼任”栈和队列:只从一端插入和删除(比如只用addFirstremoveFirst),它就变成了(后进先出);只从一端插入、另一端删除(比如addLastremoveFirst),它就变成了队列(先进先出)。所以一个双端队列能替代两种数据结构。

底层实现:双向链表 / 环形数组

双端队列有两种常见实现方式:双向链表环形数组。双向链表的每个节点有前后指针,两端操作只需修改指针,O(1) 但内存开销大。环形数组用固定大小的数组,通过头尾指针循环使用空间,操作也是 O(1),且内存更紧凑。Java 的 LinkedList 是双向链表实现,ArrayDeque 是环形数组实现,推荐使用后者。

典型应用:滑动窗口最大值

给定一个数组和一个窗口大小 k,窗口每次向右滑动一步,求每个窗口的最大值。用双端队列可以高效解决:队列中存储数组下标,保证队头是当前窗口最大值的下标。每次滑动时,从队尾移除小于新元素的下标,从队头移除已滑出窗口的下标。这样每个元素最多入队出队一次,总时间 O(n)。

吴师兄提示:记住「两头都能进出」。

学完练一练

把刚学的结构放进 LeetCode 题里用一次。

去图解题库实战