展平多级双向链表

多级双向链表中,除了指向下一个节点和前一个节点指针之外,它还有一个子链表指针,可能指向单独的双向链表。这些子列表也可能会有一个或多个自己的子项,依此类推,生成多级数据结构,如下面的示例所示。

给定位于列表第一级的头节点,请扁平化列表,即将这样的多级双向链表展平成普通的双向链表,使所有结点出现在单级双链表中。

扁平化后的链表如下图:

解题思路:

        在展平链表时,我们希望先处理一个节点的子链表,再处理它的下一个节点。这种先深入再回溯的过程正是深度优先遍历(DFS)的特点。DFS可以通过递归实现,但考虑到链表节点的修改操作(更新prev和next指针),我们选择栈来模拟递归。

        使用栈存储待处理的节点,初始时将链表头节点压入栈中。通过循环不断从栈中弹出节点进行处理,优先将next节点压入栈,然后将child节点压入栈。在处理每个节点时,更新其prev和next指针,以展平链表。

        因为栈是后进先出(LIFO),先压入的元素后弹出。为了确保在遍历当前节点的子节点之后再继续遍历它的下一个节点,我们需要先将next节点压入栈,然后再将child节点压入栈。这样,栈顶先是child节点,待子链表处理完毕后,再处理next节点,确保了正确的遍历顺序。

示例:

假设链表结构如下:

1 - 2 - 3
    |
    4 - 5
        |
        6

1的next是2。
2的child是4,next是3。
4的next是5。
5的child是6。

遍历步骤:

初始栈:[1]
弹出1,压入2。栈:[2]
弹出2,压入3,再压入4。栈:[3, 4]
弹出4,压入5。栈:[3, 5]
弹出5,压入6。栈:[3, 6]
弹出6。栈:[3]
弹出3。栈:[]
遍历顺序:1 -> 2 -> 4 -> 5 -> 6 -> 3,展平后的链表顺序是正确的。

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

class Solution {
    public Node flatten(Node head) {
        if (head == null) {
            return head;
        }

        // 使用一个伪头部(dummy head),便于处理链表的头部节点
        Node dummyHead = new Node(0);
        dummyHead.next = head;
        head.prev = dummyHead;

        // 使用一个栈来存储节点,便于深度优先遍历
        Deque<Node> stack = new ArrayDeque<>();
        stack.push(head);

        Node prev = dummyHead;

        while (!stack.isEmpty()) {
            Node curr = stack.pop();

            // 处理当前节点
            prev.next = curr;
            curr.prev = prev;

            // 如果当前节点有下一个节点,先将下一个节点压入栈中
            if (curr.next != null) {
                stack.push(curr.next);
            }

            // 如果当前节点有子节点,将子节点压入栈中
            if (curr.child != null) {
                stack.push(curr.child);
                // 处理完子节点后,将当前节点的子节点指针置为空
                curr.child = null;
            }

            // 更新前驱节点
            prev = curr;
        }

        // 断开伪头部与真实头部的连接
        dummyHead.next.prev = null;
        return dummyHead.next;
    }
}

  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不过是条河鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值