430-扁平化多级双向链表(Flatten a Multilevel Doubly Linked List)

本文介绍如何将一个多级双向链表转化为单级链表,通过遍历节点并处理子链,确保所有节点都在同一层级。讨论了算法思路,包括节点连接和特殊情况处理,并提供了代码实现。
摘要由CSDN通过智能技术生成

题目描述
中文描述:
您将获得一个双向链表,除了下一个和前一个指针之外,它还有一个子指针,可能指向单独的双向链表。这些子列表可能有一个或多个自己的子项,依此类推,生成多级数据结构,如下面的示例所示。

扁平化列表,使所有结点出现在单级双链表中。您将获得列表第一级的头部。

英文描述:
You are given a doubly linked list which in addition to the next and previous pointers, it could have a child pointer, which may or may not point to a separate doubly linked list. These child lists may have one or more children of their own, and so on, to produce a multilevel data structure, as shown in the example below.

Flatten the list so that all the nodes appear in a single-level, doubly linked list. You are given the head of the first level of the list.

示例
在这里插入图片描述
示例说明:
给出以下多级双向链表:

在这里插入图片描述
应该返回如下所示的扁平双向链表:
在这里插入图片描述
好的,题目描述到此结束,接下来分析问题。
问题本身并不难以理解,就是将一个多级链表转化为一个单级链表,这里我们利用暴力思想:首先给定头结点

  1. 如果当前结点是一个普通结点(结点不为空,结点的下一个不为空并且该结点无子链),我们就让这个结点指向这个结点的下一个结点。
if(temp != null && temp.child == null && temp.next != null){       //普通节点
                temp = temp.next;
            }
  1. 如果当前结点不为空且有子链,我们就对其进行操作。具体操作如下:
    • 首先,我们让子链的头结点的前驱(prev)指向我们当前的结点
    • 然后,我们让当前结点的子链指向null
    • 如果当前结点有下一个结点(next),则将其压栈
    • 令当前结点指向子链的头结点
else if(temp != null && temp.child != null){                             //有子节点
                Node cur = temp.child;
                temp.child = null;
                cur.prev = temp;
                if(temp.next != null){                                          //如果有下一个结点,则将其压栈
                     stack.push(temp.next);
                }
                temp.next = cur;
                temp = temp.next;                                               //更换子节点的头结点的prev后进行
            }
  1. 如果当前结点是子链的最后一个结点,我们就弹栈,并让当前结点指向弹出的结点。
 else if(temp.next == null && !stack.isEmpty()){                          //子节点的最后一个节点
                Node cur = stack.pop();
                temp.next = cur;
                cur.prev = temp;
                temp = temp.next;
            }
  1. 如果当前结点是主链的最后一个结点,则结束循环,输出结果。
else if(temp.next == null && stack.isEmpty()){
                temp.next = null;
                break;
            }

现在让我们看一下完整版代码

/*
// Definition for a Node.
class Node {
    public int val;
    public Node prev;
    public Node next;
    public Node child;

    public Node() {}

    public Node(int _val,Node _prev,Node _next,Node _child) {
        val = _val;
        prev = _prev;
        next = _next;
        child = _child;
    }
};
*/
class Solution {
    public Node flatten(Node head) {
        if(head == null)
            return head;
        if(head.next == null && head.child == null)
            return head;
        Node temp = head;
        Node res = temp;
        Stack<Node> stack = new Stack<Node>();
        while(true){
            if(temp != null && temp.child == null && temp.next != null){       //普通节点
                temp = temp.next;
            }
            else if(temp != null && temp.child != null){                             //有子节点
                Node cur = temp.child;
                temp.child = null;
                cur.prev = temp;
                if(temp.next != null){                                          //如果有下一个结点,则将其压栈
                     stack.push(temp.next);
                }
                temp.next = cur;
                temp = temp.next;                                               //更换子节点的头结点的prev后进行
            }
            else if(temp.next == null && !stack.isEmpty()){                          //子节点的最后一个节点
                Node cur = stack.pop();
                temp.next = cur;
                cur.prev = temp;
                temp = temp.next;
            }
            else if(temp.next == null && stack.isEmpty()){
                temp.next = null;
                break;
            }
        }
        return res;
    }
}

这道题目并不困难,只是其中的细节要注意,比如在连接到子链的时候注意要修改子链的prev和当前结点的child结点即可
题目中使用到了栈,大家也可以尝试使用递归来试试本题。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值