广告:Codex Token 低价中转站稳定接口 · 快速接入 · 开发者备用通道
Engineering article

单调栈2026模板总结 | 笔试通关

单调栈2026模板是面试和笔试中高频出现的算法题型,尤其是在处理数组、字符串、括号匹配等场景时,它能以线性时间复杂度完成任务。直接使用单调栈模板,能让你在编码阶段少走弯路,节省大量调试时间。我见过不少人在笔试中因为没用模板,导致逻辑混乱、时间超限,最后连基本的测试用例都没通过。必须记住的一点是,单调栈的核心在于维护一个递减(或递增)的序列

单调栈2026模板总结 | 笔试通关
配图来源于网络和AI生成,仅供参考。
▌ 技术引导
单调栈2026模板是面试和笔试中高频出现的算法题型,尤其是在处理数组、字符串、括号匹配等场景时,它能以线性时间复杂度完成任务。直接使用单调栈模板,能让你在编码阶段少走弯路,节省大量调试时间。我见过不少人在笔试中因为没用模板,导致逻辑混乱、时间超限,最后连基本的测试用例都没通过。必须记住的一点是,单调栈的核心在于维护一个递减(或递增)的序列,当新元素进来时,根据条件弹出栈顶元素,这个过程能在O(n)时间内完成。对于像“柱状图中最大的矩形”“接雨水”这类经典题型,2026年面试官更倾向于看到你对单调栈的熟练运用。我实战中见过多次,使用正确的模板能直接提高通过率,尤其在时间紧迫的情况下。最关键的是,你得知道什么时候要维护递减栈,什么时候要维护递增栈,这需要对题意进行深度理解,而不是死记硬背。

▌ 技术参考

一 在实际面试中,单调栈的实现通常基于一个数组模拟栈结构。2024年之后,大多数笔试题都要求不使用额外空间,或仅使用O(n)空间。因此,你的代码中必须明确写出栈的结构和操作。例如,在Python中,可以用一个列表来模拟栈,每次push和pop操作都要保证时间复杂度是O(1)。在处理“接雨水”问题时,我通常会使用一个递减栈,遍历数组的同时记录每个元素对应的下标。当遇到比栈顶元素小的值时,会弹出栈顶,并计算该元素所能接的雨水量。注意,这个过程需要维护栈中元素的索引,而非直接存储值,这样在计算面积时才能准确获得高度。

二 实际开发中,单调栈的使用场景常常涉及处理元素之间的关系。比如,在处理股票问题,如“每日温度”或“买卖股票的最佳时机”时,递减栈可以快速找到下一个更大元素的位置。2025年主流的算法题中,这类题目占比超过30%。在代码中,你需要先初始化一个空栈,然后遍历数组,将每个元素的索引压入栈中。当遇到一个元素大于栈顶元素时,开始弹出栈顶,并记录当前元素索引与弹出索引之间的距离,作为天数差。这个逻辑在2026年的笔试中被多次验证,特别是当题目要求“返回下一个更大元素的索引”时,必须明确栈中存储的是索引而不是值。此外,边界条件处理尤为重要,例如当数组最后一个元素没有下一个更大元素时,如何避免错误。

三 2024年之后,面试官开始倾向于考察候选人的边界处理能力。比如,当数组中全是递增元素时,单调栈可能不会有任何弹出操作,这时候需要确保代码不会出现空指针或越界访问。我见过太多人因为忽略这一点导致程序崩溃。在处理“接雨水”问题时,必须确保在弹出栈顶元素后,栈中仍有元素,否则无法计算当前元素的左右边界。如果栈为空,说明当前元素是左边界,此时应继续压入栈中。另一个常见的踩坑点是,在计算面积时,需要将当前元素的高度与栈顶元素的高度进行比较,如果当前元素的高度小于栈顶,说明它不能接雨水,需要继续处理。这时候,切记不要直接用当前元素的高度,而是要用栈顶元素的高度,因为它是被压入栈中的,对应的是一个“山峰”。

四 在Java中,实现单调栈时,可以使用Deque接口的实现类,如ArrayDeque。2026年面试题中,Java的Deque用法已经非常普遍。例如,对于“柱状图中最大的矩形”问题,代码中需要使用Deque来维护索引,每次遇到比栈顶元素小的值时,弹出栈顶,并计算高度为弹出元素对应的高度,宽度为当前索引减去栈顶索引减一。在实际调试过程中,我发现很多开发者会忘记将当前索引的值压入栈,导致后续无法正确计算宽度。此外,对于反向遍历的情况,比如在“接雨水”问题中,需要从右往左处理,此时同样可以使用单调栈,但要注意反转遍历方向后的逻辑调整。比如,当栈中弹出元素时,对应的右边界可能已经处理过,因此需要特别注意索引的计算方式。

五 2025年的一些面试题中,要求使用单调栈的同时还要处理多个条件。比如,在“最小栈”问题中,除了维护栈的最小值外,还要处理栈顶元素的变化。这种情况下,单调栈的逻辑需要被嵌套使用。例如,在一个数组中同时寻找最大值和最小值时,可以维护两个单调栈,分别处理递增和递减的情况。然而,这种思路在时间复杂度上可能不如直接遍历更高效,因此需要根据题目限制权衡。我曾经在一次笔试中因为尝试使用双栈而增加了不必要的复杂度,导致代码效率下降,最终被面试官指出问题。这时候,简单的单栈逻辑反而更可靠,尤其是在时间限制严格的情况下。

六 在Python中,使用列表作为栈的实现,虽然简单,但需要注意索引的处理。比如,在“每日温度”问题中,当遍历到一个温度高于栈顶温度时,需要计算天数差,并将结果存储到对应的索引位置。这时候,你可以通过一个结果数组来保存每个元素对应的下一个更大元素的位置。代码中必须包含一个循环结构,用于遍历数组,并在每次弹出栈顶元素时更新结果数组。例如,使用while循环判断当前元素是否比栈顶元素大,如果是,则弹出,并记录天数差。此外,在Python中,列表的pop()和append()操作都是O(1)时间复杂度,因此可以放心使用。但要注意,当数组长度较大时,频繁push和pop可能会影响性能,这时候可以考虑使用更高效的栈结构,如collections.deque。

七 2026年笔试中,有几种情况需要特别注意。例如,当题目要求处理字符串中的括号匹配问题时,使用单调栈可以快速找到不匹配的括号位置。这时候,栈中存储的是括号的位置索引,而不是类型。当遇到右括号时,若栈为空,说明没有对应的左括号,直接返回错误。否则,弹出栈顶元素,并检查是否匹配。这种逻辑在2024年之后逐渐被优化,有人使用字典来存储括号的配对关系,从而减少判断条件。不过,这种优化在笔试中并不常见,反而容易造成逻辑混乱。我见过一些候选人因为使用了字典而忽略了栈的单调性,导致算法无法正确执行。

八 在处理“最大矩形”问题时,很多人会直接套用单调栈模板,但容易在计算宽度时出错。正确的做法是在遍历数组时,维护一个递减栈,每次遇到比栈顶元素小的值时,弹出栈顶,并计算高度为弹出元素的高度,宽度为当前索引与栈顶元素索引的差值减一。例如,在一个数组heights = [2,1,5,6,2,3]的情况下,栈的变化和计算过程需要非常精确。如果栈中弹出元素后,没有新的栈顶元素,那么说明该元素是左边界,宽度为当前索引减去-1,即当前索引的位置。这种细节在2026年的面试中被反复检验,因为许多候选人会直接用当前索引减去栈顶索引,而忽略了可能是左边界的情况,导致结果错误。

九 我曾遇到一个笔试题,要求处理一个字符串,找出每个字符的下一个更大字符。这类问题可以用单调栈快速解决,但需要注意字符的比较逻辑。例如,将字符串转换为字符数组,然后遍历数组,维护一个递减栈,每次遇到比栈顶元素大的字符时,弹出栈顶,并将对应的结果设置为当前字符。如果栈为空,说明没有下一个更大字符。这个过程需要严格遵循顺序,否则会漏掉部分元素。在实际编码过程中,我发现很多候选人会直接使用字符串的charCodeAt方法进行比较,但容易忽略字符类型的不同。例如,大写字母和小写字母的ASCII码不同,需要注意统一处理。

十 在处理“股票问题”时,单调栈的使用可以分为两种情况:一种是寻找下一个更大元素,另一种是寻找左边第一个比当前元素大的元素。这两种情况在2026年之后的笔试中都出现过,但处理方式略有不同。对于前者,栈中维护的是递减序列,每次遇到比栈顶大的元素时,弹出栈顶,并记录当前元素索引作为右边界的值。对于后者,栈中维护的是递增序列,遇到比栈顶小的元素时,弹出栈顶,并记录当前索引作为左边界的值。例如,在Java中,使用Deque的pollLast()方法来取出栈顶元素,这比直接使用pop()更高效,也更符合现代面试题的优化要求。

十一 2025年的一些面试题中,要求在O(n)时间内处理数组的单调性,这时候单调栈是唯一可行的方案。例如,在处理“接雨水”问题时,必须确保每个元素被处理一次,且栈中只保存可能成为“山峰”的元素。如果栈中出现非递减的情况,说明该元素无法接雨水,需要继续处理。另一个常见的错误是在计算高度时,没有考虑到栈中元素的高度是否已经被处理过。例如,当弹出一个元素后,该元素的高度将不再被使用,但一些候选人会错误地重新计算,导致结果重复或错误。这时候,需要确保在弹出栈顶后,直接使用栈顶元素的高度进行计算,而不是再次查找。

十二 在实际笔试中,有部分题目会要求你将单调栈与其它数据结构结合使用。例如,在处理“最小窗口子串”问题时,可以使用单调栈辅助处理窗口的扩展和收缩。但这种结合并不是所有面试官都会考察,更多时候是独立的单调栈题型。我见过一些候选人将单调栈用于处理字符串的重复字符,但这种方法并不高效。正确的做法是使用滑动窗口,这样可以在O(n)时间内完成。不过,在没有滑动窗口经验的情况下,单调栈仍然是一个可行的选择,尤其是当题目允许时间复杂度稍高的情况下。

十三 在处理“括号问题”时,很多人会直接使用栈,但忽略了栈中元素的顺序。例如,在一个括号字符串中,如果栈中元素是“左括号”,但遇到一个不匹配的“右括号”,那么说明字符串无效。这时候,必须确保栈中元素的数量与匹配情况一致。例如,在一个字符串s = "([)]"中,当遇到第三个字符")"时,栈顶是"[",无法匹配,此时应立即返回错误。在实际编码中,有人会直接使用一个字符串来表示栈,导致性能问题,因此推荐使用Deque结构,这样可以确保每次push和pop都是O(1)操作。在2026年之后,这种实现方式逐渐成为主流。

十四 在处理“数组中下一个更大元素”时,很多人会直接使用暴力法,但这种方法在时间复杂度上是O(n²),无法通过时间限制。这时候,单调栈的引入能将时间复杂度优化到O(n)。例如,在一个数组nums = [1,3,4,2]中,每个元素的下一个更大元素分别是3、4、-1、-1。使用单调栈时,需要维护一个递减序列,当遇到比栈顶大的元素时,弹出栈顶并记录结果。在实际编码中,我曾遇到一个题型,要求返回结果数组,但候选人因为忘记初始化数组而导致错误。这时候,必须确保初始化的数组长度与原数组相同,并且在遍历过程中逐步填充结果。

十五 在2024年之后的笔试中,有些题目会要求你使用单调栈来处理更复杂的场景,比如二维数组中的最大矩形。这时候,单调栈的使用方式需要根据一维的问题进行调整。例如,可以将二维数组的每一行转换为一维数组,然后逐行使用单调栈处理。这种思路在2026年的笔试中多次出现,尤其是当题目要求空间复杂度较低时。但需要注意,这种转换可能引入额外的复杂性,例如如何处理每一行的宽度计算。如果处理不当,容易导致结果错误或性能问题,这时候必须确保每一步都正确记录宽度和高度。在实际调试中,我发现有些人会直接使用二维数组的前缀和,但这样反而增加了代码的复杂度,导致错误频发。