单次循环解决“下一个更大元素”的核心是单调栈主动匹配:遍历中每个数先弹出所有小于它的栈顶索引并填入结果,再将自身下标入栈;栈存索引以准确定位结果位置,维持栈底到栈顶对应数值严格递减,边界初始化top=-1,结果数组预填-1,循环数组用i%n取模实现。
单次循环解决“下一个更大元素”,核心是用单调栈把“被动等待”变成“主动匹配”:遍历每个数时,它不光是找自己的答案,还帮前面那些比它小的数“结案”。关键不在栈本身,而在每次入栈前,先清掉所有能被当前数“盖过”的栈顶元素。
栈里存什么?必须是索引
存数值看似简单,但无法定位该填到结果数组哪个位置。栈中只存原始下标(比如 i),这样弹出时才能准确写入 result[idx] = nums[i]。哪怕题目只要求返回值,也建议先存索引——逻辑清晰、不易错,后续扩展(如同时要下标和值)也方便。
单调性怎么控?维持栈底到栈顶严格递减
目标是找“右边第一个更大”,所以栈内对应数值必须从底到顶越来越小。这样一旦遇到 nums[i] > nums[stack[top]],就能断定:当前 i 就是栈顶索引所指元素的答案。
- 入栈前,用 while (top >= 0 && nums[i] > nums[stack[top]]) 持续弹出
- 每次弹出后立即更新 result[stack[top--]] = nums[i]
- 弹完再把 i 压入:stack[++top] = i
边界与初始化不能跳步
数组模拟栈,细节决定成败:
- 栈数组长度设为 nums.length 即可,无需更大(每个下标最多入栈一次)
- top 初始必须是 -1,不是 0;判空用 top == -1
- 结果数组提前全填 -1,栈中剩余索引自然保持默认值,不用额外扫尾
- 比较时先取 nums[stack[top]] 存为局部变量,避免重复寻址
循环数组怎么办?不拼接,只取模
面对首尾相连场景(如 LeetCode 503),不必复制数组浪费空间。把外层循环跑 2 * n - 1 轮,每次真实下标用 i % n 计算即可。栈中仍存原始索引(0 到 n−1),结果数组按原位置更新,逻辑干净,内存零冗余。










