「这是我参与2022首次更文挑战的第26天,活动详情查看:2022首次更文挑战」
430. 扁平化多级双向链表
你会得到一个双链表,其中包含的节点有一个下一个指针、一个前一个指针和一个额外的 子指针 。这个子指针可能指向一个单独的双向链表,也包含这些特殊的节点。这些子列表可以有一个或多个自己的子列表,以此类推,以生成如下面的示例所示的 多层数据结构 。
给定链表的头节点 head ,将链表 扁平化 ,以便所有节点都出现在单层双链表中。让 curr 是一个带有子列表的节点。子列表中的节点应该出现在扁平化列表中的 curr 之后 和 curr.next 之前 。
返回 扁平列表的 head 。列表中的节点必须将其 所有 子指针设置为 null 。
示例1:
输入: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]
解释:输入的多级列表如上图所示。
扁平化后的链表如下图:
示例2:
输入: head = [1,2,null,3]
输出: [1,3,2]
解释: 输入的多级列表如上图所示。
扁平化后的链表如下图:
示例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
};