本文详解使用单调栈(从右向左遍历)求解「下一个更大元素」问题的标准解法,修正常见索引错位与栈维护逻辑错误,并提供可直接运行的健壮实现。
本文详解使用单调栈(从右向左遍历)求解「下一个更大元素」问题的标准解法,修正常见索引错位与栈维护逻辑错误,并提供可直接运行的健壮实现。
「下一个更大元素」(Next Greater Element, NGE)是经典的栈应用问题:对数组中每个元素 arr[i],找出其右侧第一个严格大于它的值;若不存在,则返回 -1。虽然直觉上可对每个元素向右线性扫描(O(n²)),但借助单调递减栈并逆序遍历,可在 O(n) 时间内高效解决。
关键在于理解栈的语义:我们维护一个从栈底到栈顶严格递减的栈,它保存的是「尚未找到 NGE 的候选元素」。当从右往左遍历(i = n-2 到 0)时,对于当前元素 arr[i]:
以下是符合标准、通过全部测试用例的实现:
function nextGreaterElement(arr) { if (arr.length === 0) return []; const n = arr.length; const result = new Array(n).fill(-1); const stack = []; // 存储元素值(非索引),维持单调递减 // 从右往左遍历 for (let i = n - 1; i >= 0; i--) { // 弹出所有小于等于当前元素的值(破坏单调性的元素) while (stack.length > 0 && stack[stack.length - 1] <= arr[i]) { stack.pop(); } // 若栈非空,栈顶即为下一个更大元素 if (stack.length > 0) { result[i] = stack[stack.length - 1]; } // 当前元素入栈,作为左侧元素的候选NGE stack.push(arr[i]); } return result;}// 测试用例验证console.log(nextGreaterElement([56, 23, 1, 5, 18, 17])); // 输出: [-1, -1, 5, 18, -1, -1]console.log(nextGreaterElement([70, 60, 1, 4, 8, 12, 50, 23])); // 输出: [-1, -1, 4, 8, 12, 50, -1, -1]console.log(nextGreaterElement([1, 2, 3, 4, 5])); // 输出: [2, 3, 4, 5, -1]console.log(nextGreaterElement([5, 4, 3, 2, 1])); // 输出: [-1, -1, -1, -1, -1]
⚠️ 注意事项与常见误区:
立即学习“Java免费学习笔记(深入)”;
该解法是 LeetCode 第 496 题「Next Greater Element I」及变体的标准基础,掌握其逆序+单调栈思想,即可延伸解决循环数组 NGE(如第 503 题)或带索引映射的复杂场景。