LeetCode-430. 扁平化多级双向链表-题解

 题目链接

430. 扁平化多级双向链表 - 力扣(LeetCode)

题目介绍

你将得到一个双链表,节点包含一个“下一个”指针、一个“前一个”指针和一个额外的“子指针”。这个子指针可能指向一个单独的双向链表,并且这些链表也包含类似的特殊节点。子列表可以有一个或多个自己的子列表,从而形成多层数据结构。

给定链表的头节点head,需要将链表扁平化,使所有节点都出现在单层双链表中。对于带有子列表的节点curr,子列表中的节点应该位于扁平化列表中curr之后,以及curr.next之前。

返回扁平化后的列表头head,列表中的节点的所有子指针必须设置为null

题目知识点

涉及到高级数据双向链表(主要考察点 - 修改指针指向模拟符合题目要求)

/*

// Definition for a Node.

class Node {

public:

    int val;

    Node* prev;

    Node* next;

    Node* child;

};

*/

 题目示例

题目分析

 我们通过题目可以清晰地了解到该题目的目的很简单,只是通过模拟来完成扁平化处理,那么对于题目而言是什么是扁平化呢,只有当包含有子指针时才会有扁平化操作,因此只是一个遍历当前节点并找到没有子指针结束的节点,不断的递归。(该方法的模拟在第二解中有所提示)

那么该题目还可以通过另一种方式来完成,这是一个重复的扁平化过程,含有子指针的双向链表的未结点会指向当前节点下一个节点,当前节点指向孩子节点的双向链表,重复扁平化处理双向链表即可,我们可以通过一个方法来模拟这个过程 // 传入一个头节点,返回一个扁平化后的未结点 //。

最后一种方式,是借助栈的特性(先进后出)用来模拟递归行为,栈可以帮助我们记录节点,先处理 child 链表,再处理 next 链表。当处理完 child 后,将 next 节点推入栈,以便之后继续处理。

代码示例:

Node* flattenList(Node* head)

    {

        Node *tmp = head ;

        while (tmp)

        {

            if (tmp -> child)

            {

                Node *phead = tmp -> child ;

                Node *ptail = flattenList(phead) ;

                ptail -> next = tmp -> next ;

                if (tmp -> next)

                {

                    tmp -> next -> prev = ptail ;

                }

                tmp -> next = phead ;

                phead -> prev = tmp ;

                tmp -> child = nullptr ;

            }

            tmp = tmp -> next ;

        }

        tmp = head ;

        while (tmp -> next) tmp = tmp -> next ;

        return tmp ;

    }

 完整代码

// 方法二
class Solution {
    // 传入一个头节点,返回一个扁平化后的未结点
    Node* flattenList(Node* head)
    {
        Node *tmp = head ;
        while (tmp)
        {
            if (tmp -> child)
            {
                Node *phead = tmp -> child ;
                Node *ptail = flattenList(phead) ;

                ptail -> next = tmp -> next ;
                if (tmp -> next)
                {
                    tmp -> next -> prev = ptail ;
                }
                tmp -> next = phead ;
                phead -> prev = tmp ;

                tmp -> child = nullptr ;
            }
            tmp = tmp -> next ;
        }
        tmp = head ;
        while (tmp -> next) tmp = tmp -> next ;
        return tmp ;

    }
public:
    Node* flatten(Node* head) {
        if (head == nullptr)
        {
            return head;
        }
        flattenList(head) ;  
        return head ; 
    }
};

 

 

"""
# Definition for a Node.
class Node:
    def __init__(self, val, prev, next, child):
        self.val = val
        self.prev = prev
        self.next = next
        self.child = child
"""
def flattenList(head) :
        if not head : 
            return head
        tmp = head
        while tmp :
            if tmp.child : 
                phead = tmp.child
                ptail = flattenList(phead)

                ptail.next = tmp.next
                if tmp.next : 
                    tmp.next.prev = ptail
                tmp.next = phead
                phead.prev = tmp
                tmp.child = None
            tmp = tmp.next
        while head and head.next :
            head = head.next
        return head
class Solution:
    def flatten(self, head: 'Optional[Node]') -> 'Optional[Node]':
        if not head :
            return head
        flattenList(head)
        return head
// 方法三

class Solution {
public:
    Node* flatten(Node* head) {
        if (!head) return nullptr ;
        stack <Node*> stack ;
        auto curr = head ;

        while (curr)
        {
            if (curr -> child)
            {
                if (curr -> next)
                {
                    stack.push(curr -> next) ;
                }
                curr -> next = curr -> child ;
                curr -> child -> prev = curr ;
                curr -> child = nullptr ;
            }

            if (!curr -> next && !stack.empty())
            {
                curr -> next = stack.top() ;
                stack.pop() ;
                curr -> next -> prev = curr ;
            }
            curr = curr -> next ;
        }
        return head ;
    }
};

 

# 方法三 - 栈(stack)python
"""
# Definition for a Node.
class Node:
    def __init__(self, val, prev, next, child):
        self.val = val
        self.prev = prev
        self.next = next
        self.child = child
"""

class Solution:
    def flatten(self, head: 'Optional[Node]') -> 'Optional[Node]':
        if not head :
            return None
        stack = []
        curr = head

        while curr :
            if curr.child :
                if curr.next :
                    stack.append(curr.next)
                curr.next = curr.child
                curr.child.prev = curr
                curr.child = None
            if not curr.next and stack :
                curr.next = stack.pop()
                curr.next.prev = curr
            curr = curr.next
        return head
        

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/927446.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

arkTS:持久化储存UI状态的基本用法(PersistentStorage)

arkUI&#xff1a;持久化储存UI状态的基本用法&#xff08;PersistentStorage&#xff09; 1 主要内容说明2 例子2.1 持久化储存UI状态的基本用法&#xff08;PersistentStorage&#xff09;2.1.1 源码1的相关说明2.1.1.1 数据存储2.1.1.2 数据读取2.1.1.3 动态更新2.1.1.4 显示…

AI 助力开发新篇章:云开发 Copilot 深度体验与技术解析

本文 一、引言&#xff1a;技术浪潮中的个人视角1.1 AI 和低代码的崛起1.2 为什么选择云开发 Copilot&#xff1f; 二、云开发 Copilot 的核心功能解析2.1 自然语言驱动的低代码开发2.1.1 自然语言输入示例2.1.2 代码生成的模块化支持 2.2 实时预览与调整2.2.1 实时预览窗口功能…

AI高中数学教学视频生成技术:利用通义千问、MathGPT、视频多模态大模型,语音大模型,将4个模型融合 ,生成高中数学教学视频,并给出实施方案。

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下AI高中数学教学视频生成技术&#xff1a;利用通义千问、MathGPT、视频多模态大模型&#xff0c;语音大模型&#xff0c;将4个模型融合 &#xff0c;生成高中数学教学视频&#xff0c;并给出实施方案。本文利用专家模…

【前端Vue】day04

一、学习目标 1.组件的三大组成部分&#xff08;结构/样式/逻辑&#xff09; ​ scoped解决样式冲突/data是一个函数 2.组件通信 组件通信语法父传子子传父非父子通信&#xff08;扩展&#xff09; 3.综合案例&#xff1a;小黑记事本&#xff08;组件版&#xff09; 拆分…

嵌入式系统应用-LVGL的应用-平衡球游戏 part2

平衡球游戏 part2 4 mpu60504.1 mpu6050 介绍4.2 电路图4.3 驱动代码编写 5 游戏界面移植5.1 移植源文件5.2 添加头文件 6 参数移植6.1 4 mpu6050 4.1 mpu6050 介绍 MPU6050是一款由InvenSense公司生产的加速度计和陀螺仪传感器&#xff0c;广泛应用于消费电子、机器人等领域…

每日十题八股-2024年12月2日

1.你知道有哪个框架用到NIO了吗&#xff1f; 2.有一个学生类&#xff0c;想按照分数排序&#xff0c;再按学号排序&#xff0c;应该怎么做&#xff1f; 3.Native方法解释一下 4.数组与集合区别&#xff0c;用过哪些&#xff1f; 5.说说Java中的集合&#xff1f; 6.Java中的线程…

git 常用命令及问题

一、常用命令 git add filename git add . git commit -m "messge" git commit --amend 修改最近一次的提交 git push origin HEAD:refs/for/master git clone url git checkout branchname 切换分支 git branch -r 查看远程仓库分支列表 git branch br…

DSD-DA

adversarial loss L a d v _{adv} adv​ g() denotes the project function&#xff0c;Gradient Reverse Layer(GRL). ROI features F ( r ) (r) (r) 补充信息 作者未提供代码

医院管理系统

私信我获取源码和万字论文&#xff0c;制作不易&#xff0c;感谢点赞支持。 医院管理系统 摘要 随着信息互联网信息的飞速发展&#xff0c;医院也在创建着属于自己的管理系统。本文介绍了医院管理系统的开发全过程。通过分析企业对于医院管理系统的需求&#xff0c;创建了一个计…

SpringBoot 整合 Avro 与 Kafka

优质博文&#xff1a;IT-BLOG-CN 【需求】&#xff1a;生产者发送数据至 kafka 序列化使用 Avro&#xff0c;消费者通过 Avro 进行反序列化&#xff0c;并将数据通过 MyBatisPlus 存入数据库。 一、环境介绍 【1】Apache Avro 1.8&#xff1b;【2】Spring Kafka 1.2&#xf…

Win10+Ubuntu20.04双系统重装Ubuntu22.04单系统

从去年 8 月美化 Ubuntu 系统后一直存在内核错误问题&#xff0c;但因为大部分功能还能正常使用&#xff0c;只是在 apt 时报错&#xff0c;所以一直逃避不想重装&#xff0c;直到最近 12 月新的开始&#xff0c;恰好设置的界面打不开得重装 gnome &#xff0c;所以下定决心重装…

Linux:进程间通信之system V

一、共享内存 进程间通信的本质是让不同的进程看到同一份代码。 1.1 原理 第一步&#xff1a;申请公共内存 为了让不同的进程看到同一份资源&#xff0c;首先我们需要由操作系统为我们提供一个公共的内存块。 第二步&#xff1a;挂接到要通信进程的地址空间中 &#xff…

Vue进阶之单组件开发与组件通信

书接上篇&#xff0c;我们了解了如何快速创建一个脚手架&#xff0c;现在我们来学习如何基于vite创建属于自己的脚手架。在创建一个新的组件时&#xff0c;要在新建文件夹中打开终端创建一个基本的脚手架&#xff0c;可在脚手架中原有的文件中修改或在相应路径重新创建&#xf…

【Linux网络编程】第四弹---构建UDP服务器与字典翻译系统:源码结构与关键组件解析

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】【Linux系统编程】【Linux网络编程】 目录 1、UdpServer.hpp 1.1、函数对象声明 1.2、Server类基本结构 1.3、构造函数 1.4、Start() 2、Dict.hpp…

数字IC后端设计实现之分段长clock tree经典案例

最近发现很多读者问到分段长clock tree的做法&#xff0c;小编今天给大家分享几个SoC芯片中复杂时钟结构设计的分段长clock tree的应用案例。希望对各位的学习和工作有所助益。 数字后端设计实现之时钟树综合实践篇 数字IC后端实现专家都具备哪些技能&#xff1f;&#xff08…

计算机毕业设计Spark+SpringBoot旅游推荐系统 旅游景点推荐 旅游可视化 旅游爬虫 景区客流量预测 旅游大数据 大数据毕业设计

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

EasyMedia播放rtsprtmp视频流

学习链接 MisterZhang/EasyMedia - gitee地址 EasyMedia转码rtsp视频流flv格式&#xff0c;hls格式&#xff0c;H5页面播放flv流视频 文章目录 学习链接介绍步骤easydarwin启动rtsp服务&#xff0c;ffmpeg推送摄像头&#xff08;模拟rtsp视频流&#xff09;nginx添加rtmp支持…

【Linux】开启你的Linux之旅:初学者指令指南

Linux相关知识点可以通过点击以下链接进行学习一起加油&#xff01; 在 Linux 开发中&#xff0c;GDB 调试器和 Git 版本控制工具是开发者必备的利器。GDB 帮助快速定位代码问题&#xff0c;Git 则提供高效的版本管理与协作支持。本指南将简明介绍两者的核心功能与使用技巧&…

SpringBoot-问题排查 Controller全局打印入参,返回值,响应时间,异常日志

问题: 想要打印每次请求的入参,返回值,响应时间,异常日志,如果给每个方法挨个添加打印日志非常麻烦 解决方案: 使用切面的方式将所有的Controller每个方法加入切入点使用环绕通知的方式可以在切入点执行前后执行切面,符合我们的需求在方法执行前后打印相关日志忽略LogIgnore注解…

mysql数据库varchar截断问题

用了这么多年mysql数据库&#xff0c;才发现varchar是可以截断的&#xff0c;而且是在我们线上数据库。个人觉得dba的这个设置是非常有问题的&#xff0c;用户往数据库里存东西&#xff0c;就是为了以后用的&#xff0c;截断了存放&#xff0c;数据不完整&#xff0c;就用不了了…