[路飞]_程序员必刷力扣题: 430. 扁平化多级双向链表

89 阅读2分钟

「这是我参与2022首次更文挑战的第26天,活动详情查看:2022首次更文挑战

430. 扁平化多级双向链表

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

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

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

示例1:

image.png

输入:head = [1,2,3,4,5,6,null,null,null,7,8,9,10,null,null,11,12]
输出:[1,2,3,7,8,11,12,9,10,4,5,6]
解释:输入的多级列表如上图所示。

扁平化后的链表如下图:

image.png

示例2: image.png

输入: head = [1,2,null,3]
输出: [1,3,2]
解释: 输入的多级列表如上图所示。

扁平化后的链表如下图:

image.png

示例3:

输入: head = []
输出: []
说明: 输入中可能存在空列表。

提示:

  • 节点数目不超过 1000
  • 1 <= Node.val <= 105

思路

由题意可知,给定我们一个双向链表,每个节点都存在一个child,如果child不为空,那么需要将child的双向链表压平,顺序为 节点的prev -> 节点 -> 节点的child -> 节点的next

这里我们使用栈的思想

我们需要whild循环节点,终止条件为!(!newHead.next && !newHead.child && !stack.length),即,节点没有child,没有next,且stack为空,那么该链表处理完毕

声明指针newHead从链表头部开始循环处理每一个节点

  • 当前节点是否有child节点,有则处理child和next的关系
    • 将child和next保存起来,next压入stack中,节点的child置为null,然后将保存的child拼接在当前节点的next位置,注意处理prev
  • 接着判断当前节点是否有next节点
    • 有则newHead = newHead.next
    • 否则证明到达某分支的末尾,此时判断stack中是否有元素,我们成为拐点
      • 有拐点则pop弹出拐点,将拐点衔接在当前节点的next位置,接着继续让newHead = newHead.next
  • 循环以上步骤

最后返回head即可

var flatten = function (head) {
    if (!head) return head
    var stack = []
    var newHead = head
    while (!(!newHead.next && !newHead.child && !stack.length)) {
        // 是否有child节点,有则处理child和next的关系
        if (newHead.child) {
            var next = newHead.next
            //保存next拐点
            if (next) stack.push(next)
            var child = newHead.child
            newHead.child = null
            // 衔接链表
            newHead.next = child
            child.prev = newHead
        }
        // 是否有next节点
        if (newHead.next) {
            // 下一个节点
            newHead = newHead.next
        } else if (stack.length) {
            // 是否存在拐点
            var next = stack.pop()
            // 衔接链表
            newHead.next = next
            next.prev = newHead
            // 下一个节点
            newHead = newHead.next
        }
    }
    return head
};