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

leetcode430:扁平化多级双向链表

https://leetcode.cn/problems/flatten-a-multilevel-doubly-linked-list

你会得到一个双链表,其中包含的节点有一个下一个指针、一个前一个指针和一个额外的 子指针 。这个子指针可能指向一个单独的双向链表,也包含这些特殊的节点。这些子列表可以有一个或多个自己的子列表,以此类推,以生成如下面的示例所示的 多层数据结构 。

给定链表的头节点 head ,将链表 扁平化 ,以便所有节点都出现在单层双链表中。让 curr 是一个带有子列表的节点。子列表中的节点应该出现在扁平化列表中的 curr 之后 和 curr.next 之前 。

返回 扁平列表的 head 。列表中的节点必须将其 所有 子指针设置为 null 。

简单来说就是把多层的链表通过插入合成一条链表

自用,感觉dfs版比较绕,得多复习几次,很容易出错

方法1:递归

出现这种一级一级嵌套很容易想到使用递归,但是递归的代码没有那么好写

class Solution {
public:Node* flatten(Node* head) {Node* curr = head;while (curr) {if (curr->child) {Node* next = curr->next;Node* childHead = flatten(curr->child);// 插入 child 链表curr->next = childHead;childHead->prev = curr;curr->child = nullptr;// 找到 child 链表的尾部Node* tail = childHead;while (tail->next) {tail = tail->next;}// 把尾部和原来的 next 连接if (next) {tail->next = next;next->prev = tail;}}curr = curr->next;}return head;}
};

首先要明确要干什么

在每一层递归中要完成断开原来的连接,把断开的位置接上

在当前层循环中完成两件事,其一是检测当前层的每一个节点的child指针是否为空

其二是完成相关的连接

在if语句内部也完成两件事,分别是平坦化和连接

但是我们会注意到

由于递归使得主链的curr指针总是把之前走过的点又走一遍

比如:这里虽然你已经平坦化,并把下面的部分都插入到了3和4之间,但是由于curr指针仍然在3,想要走到4仍然要沿着绿线走一遍,增加了时间复杂度

所以我们就可以考虑记录每一次的链表末尾,

如果有一个函数能同时完成平坦化并且返回链表末尾的指针就好了,

但是原函数返回的是链表的头指针,因此我们得自己写一个函数辅助

方法2:递归+dfs函数优化

这里参考力扣官方题解

class Solution {
public:Node* flatten(Node* head) {function<Node*(Node*)> dfs = [&](Node* node) {Node* cur = node;// 记录链表的最后一个节点Node* last = nullptr;while (cur) {Node* next = cur->next;//  如果有子节点,那么首先处理子节点if (cur->child) {Node* child_last = dfs(cur->child);next = cur->next;//  将 node 与 child 相连cur->next = cur->child;cur->child->prev = cur;//  如果 next 不为空,就将 last 与 next 相连if (next) {child_last->next = next;next->prev = child_last;}// 将 child 置为空cur->child = nullptr;last = child_last;}else {last = cur;}cur = next;}return last;};dfs(head);return head;}
};作者:力扣官方题解
链接:https://leetcode.cn/problems/flatten-a-multilevel-doubly-linked-list/solutions/1013884/bian-ping-hua-duo-ji-shuang-xiang-lian-b-383h/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

其中函数的主要部分就是这个dfs函数

补充:关于lambda表达式

其实只是把「递归函数」定义成 lambda 表达式,再存到 std::function 里,以便 lambda 内部能调用自己(实现递归)。
拆开看就四件事:

  1. std::function<Node*(Node*)>
    一个函数对象类型,签名是「接收 Node*,返回 Node*」。

  2. dfs
    变量名,后面用它来递归。

  3. = [&]
    捕获列表

    • [&] 表示「所有外部变量按引用捕获」,这样 lambda 里才能看见并调用 自己(dfs)

  4. (Node* node) { ... }
    真正的函数体,和普通函数写法一模一样。

假如孩子指针全为空,代码执行

class Solution {
public:Node* flatten(Node* head) {function<Node*(Node*)> dfs = [&](Node* node) {Node* cur = node;// 记录链表的最后一个节点Node* last = nullptr;while (cur) {Node* next = cur->next;last = cur;cur = next;}return last;};dfs(head);return head;}
};这样相当于就遍历了一次链表,返回了最后一个位置,也是没有问题的

http://www.dtcms.com/a/422780.html

相关文章:

  • 网站项目开发收费标准360网站名片怎么做的
  • 分布式秒杀系统设计方案
  • 分布式短链接系统设计方案
  • 分布式光纤声波振动与AI的深度融合:开启智慧感知新时代
  • 电商网站设计论文新网金商网站
  • [pdf、epub]320道《软件方法》强化自测题业务建模需求分析共279页(202509更新)
  • 赎金信--leetcode
  • Harbor磁盘空间清理指南:如何安全清理半年前的镜像
  • 网站开发项目组织架构电商平台怎么找商家
  • 基于Hadoop的肾脏疾病风险分析系统架构设计精髓
  • 如何优雅的布局,height: 100% 的使用和 flex-grow: 1 的 min-height 陷阱
  • Ubuntu20.04使用venv创建虚拟环境并安装ultralytics
  • Docker 镜像知识总结
  • 东莞保安公司2019网站seo
  • 34.MariaDB 数据库
  • Gradle之适配
  • 实战:爬取豆瓣电影Top250,并生成Excel榜单
  • 建网站有什么要求山西网站建设方案
  • The Goldfeld–Quandt test
  • 第一章:Alertmanager基础概念与架构
  • 【C语言内存函数完全指南】:memcpy、memmove、memset、memcmp 的用法、区别与模拟实现(含代码示例)
  • 学习React-19-useDebugValue
  • Python实现网站/网页管理小工具
  • 魏公村网站建设城阳做网站的公司
  • 【笔记】介绍 WPF XAML 中 Binding 的 StringFormat详细功能
  • 【XR行业应用】XR + 医疗:重构未来医疗服务的技术革命与实践探索
  • 微服务-Nacos 技术详解
  • 天津高端网站建设企业旅游品牌网站的建设
  • 51单片机-实现DAC(PWM)数模转换PWM控制呼吸灯、直流电机实验教程
  • VMware安装虚拟机并且部署 CentOS 7 指南