当前位置: 首页 > news >正文

【算法】1019.链表中的下一个更大节点--通俗讲解

一、题目是啥?一句话说清

给定一个链表,对于每个节点,找到它后面第一个值比它大的节点,如果没有则返回0。

示例:

  • 输入:2 → 7 → 4 → 3 → 5
  • 输出:[7, 0, 5, 5, 0]

二、解题核心

使用单调栈:遍历链表,维护一个单调递减的栈,当遇到比栈顶元素大的节点时,说明找到了栈顶元素的下一个更大节点。

这就像排队时,每个人都在找前面第一个比自己高的人,如果找到了就记住他的身高,找不到就记0。

三、关键在哪里?(3个核心点)

想理解并解决这道题,必须抓住以下三个关键点:

1. 单调栈的使用

  • 是什么:维护一个栈,栈中存储的是节点的索引和值,保持栈中元素的值单调递减。
  • 为什么重要:单调栈可以高效地找到每个元素的下一个更大元素,时间复杂度为O(n)。

2. 栈中存储索引

  • 是什么:在栈中存储节点的索引(位置),而不是节点本身。
  • 为什么重要:这样我们可以知道当前节点对应结果数组中的哪个位置,从而正确设置结果值。

3. 逆序处理

  • 是什么:将链表转换为数组后,从后往前处理,或者使用栈来模拟逆序处理。
  • 为什么重要:因为要找的是"下一个"更大节点,从后往前处理可以确保我们处理当前节点时,已经知道了后面所有节点的信息。

四、看图理解流程(通俗理解版本)

假设链表为:2 → 7 → 4 → 3 → 5

  1. 转换为数组:[2, 7, 4, 3, 5]
  2. 初始化:结果数组ans = [0, 0, 0, 0, 0],栈stack为空
  3. 从后往前处理
    • i=4(值5):栈空,ans[4]=0,压入5
    • i=3(值3):栈顶5>3,ans[3]=5,压入3
    • i=2(值4):栈顶3<4,弹出3;栈顶5>4,ans[2]=5,压入4
    • i=1(值7):栈顶4<7,弹出4;栈顶5<7,弹出5;栈空,ans[1]=0,压入7
    • i=0(值2):栈顶7>2,ans[0]=7,压入2
  4. 最终结果:[7, 0, 5, 5, 0]

五、C++ 代码实现(附详细注释)

#include <iostream>
#include <vector>
#include <stack>
using namespace std;// 链表节点定义
struct ListNode {int val;ListNode *next;ListNode() : val(0), next(nullptr) {}ListNode(int x) : val(x), next(nullptr) {}ListNode(int x, ListNode *next) : val(x), next(next) {}
};class Solution {
public:vector<int> nextLargerNodes(ListNode* head) {// 第一步:将链表转换为数组vector<int> nums;ListNode* current = head;while (current != nullptr) {nums.push_back(current->val);current = current->next;}int n = nums.size();vector<int> result(n, 0); // 初始化结果数组,全部为0stack<int> st; // 单调栈,存储数组索引// 第二步:使用单调栈找到下一个更大节点for (int i = 0; i < n; i++) {// 当栈不为空且当前元素大于栈顶元素时while (!st.empty() && nums[i] > nums[st.top()]) {// 找到了栈顶元素的下一个更大节点result[st.top()] = nums[i];st.pop();}// 将当前索引入栈st.push(i);}return result;}
};// 辅助函数:打印数组
void printVector(const vector<int>& vec) {for (int num : vec) {cout << num << " ";}cout << endl;
}// 测试代码
int main() {// 构建示例链表:2->7->4->3->5ListNode* head = new ListNode(2);head->next = new ListNode(7);head->next->next = new ListNode(4);head->next->next->next = new ListNode(3);head->next->next->next->next = new ListNode(5);Solution solution;vector<int> result = solution.nextLargerNodes(head);printVector(result); // 输出:7 0 5 5 0// 释放内存while (head != nullptr) {ListNode* temp = head;head = head->next;delete temp;}return 0;
}

六、时间空间复杂度

  • 时间复杂度:O(n),其中n是链表长度。每个元素最多入栈一次、出栈一次。
  • 空间复杂度:O(n),用于存储数组和栈,最坏情况下栈的大小为n。

七、注意事项

  • 单调栈性质:栈中元素保持单调递减,这样当遇到更大的元素时,可以确定栈中哪些元素找到了下一个更大节点。
  • 索引存储:栈中存储的是索引而不是值,这样我们可以知道结果应该放在哪个位置。
  • 边界处理:处理空链表的情况,以及链表只有一个节点的情况。
  • 结果初始化:结果数组初始化为0,这样如果没有找到更大节点,结果自然就是0。
  • 严格大于:题目要求严格大于,所以比较时使用>而不是>=
  • 链表转数组:先将链表转换为数组可以简化索引管理,如果不想转换,也可以直接处理链表,但需要记录每个节点的位置信息。
http://www.dtcms.com/a/469689.html

相关文章:

  • 福州seo建站互联网营销师考试题库
  • Flutter中的动效实现方式
  • Agent 的感知-决策-行动循环实现
  • Azure托管标识完整指南:安全无密码的云身份验证
  • Azure Front Door 在中国区正式上线
  • 基础 - 正则表达式
  • 旅游网站系统网站上设置多语言怎么做
  • 第三方软件验收测试公司【如何深入理解SSL/TLS证书】
  • JavaWeb——ServletConfig
  • QwenVL - 202310版-论文阅读
  • 如何从 FastReport .NET 将报表导出为 JPEG / PNG / BMP / GIF / TIFF / EMF
  • .NET MCP Server 开发教程
  • LeetCode 124. 二叉树中的最大路径和(困难)
  • 建设南大街小学网站wordpress首页调用指定文章列表
  • 大型语言模型(LLM)基础:从原理到核心概念详解(GPT-4 / 文心一言 / 通义千问)
  • python高级03——多任务编程
  • 树模型优劣大比拼xgboost/lightgbm/RF/catboost,股价预测怎么选模型
  • 哈尔滨快速建站公司推荐营销型网站建设实战》
  • 4.3-中间件之Kafka
  • 方寸之间见天地:新兴高端印章的当代破局与价值重构
  • 如何改善基于深度学习的场重构
  • Maven 进行项目构建settings.xml 配置教程
  • 磁力搜索网站怎么做的网站和app设计区别
  • 西安网站建设公司都有哪些网站设计开发文档模板下载
  • C++设计模式_结构型模式_桥接模式Bridge
  • 关于flutter插件的存储位置问题
  • 把“Mixed Content”吃干抹净——一次 https→http 踩坑实录
  • 中山大学联合项目 论文解读 | iManip:面向机器人操作的技能增量学习
  • Unity:Json笔记——Json文件格式、JsonUtlity序列化和反序列化
  • 第八章 惊喜15 小萍收获初会