「这是我参与2022首次更文挑战的第8天,活动详情查看:2022首次更文挑战」。
每日刷题第30天 2021.1.26
扁平化多级双向链表
- leetcode原题链接:leetcode-cn.com/problems/fl…
- 难度:中等
- 方法:链表,dfs(深度优先遍历)
题目
- 多级双向链表中,除了指向下一个节点和前一个节点指针之外,它还有一个子链表指针,可能指向单独的双向链表。这些子列表也可能会有一个或多个自己的子项,依此类推,生成多级数据结构,如下面的示例所示。
- 给你位于列表第一级的头节点,请你扁平化列表,使所有结点出现在单级双链表中。
示例
示例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]
解释:
输入的多级列表如下图所示:
1---2---NULL
|
3---NULL
示例3
输入: head = []
输出: []
提示
- 节点数目不超过
1000 1 <= Node.val <= 10^5
解法
- 使用dfs深度优先遍历,先遍历child,再遍历next
- 当前节点没有child,则继续往后遍历next
- 当前节点有child,则往下遍历child节点
- 注意1⚠️:不要在dfs遍历的过程中去修改next指针的指向,否则会有死循环情况。
- 解决方法:在dfs遍历的过程中,只做记录节点的操作,最后再将记录好的节点,依次连接成一个新的节点进行返回。
- 注意⚠️2:函数的返回值要多注意,不要题目要求返回一个node头节点,而自己返回的是一个数组!!!!
- 利用
flatten函数本身的含义(将链表头为head的链表进行扁平化,并将扁平化后的头结点进行返回),我们可以很容易写出递归版本。 - 为防止空节点等边界问题,起始时建立一个哨兵节点
dummy指向head,然后利用head指针从前往后处理链表: - 当前节点
head没有child节点:直接让指针后即可,即head = head.next - 当前节点
head有child节点:将head.child传入flatten函数递归处理,拿到普遍化后的头结点chead,然后将head和chead建立“相邻”关系(注意要先存起来原本的tmp = head.next以及将head.child置空),然后继续往后处理,直到扁平化的chead链表的尾部,将其与tmp建立“相邻”关系。 - 重复上述过程,直到整条链表被处理完。
/**
* // Definition for a Node.
* function Node(val,prev,next,child) {
* this.val = val;
* this.prev = prev;
* this.next = next;
* this.child = child;
* };
*/
/**
* @param {Node} head
* @return {Node}
*/
var flatten = function(head) {
let ans = [];
function dfs (node) {
if (node == null) return;
// console.log('node', node.val);
ans.push(node);
if(node.child != null) dfs(node.child);
if(node.next != null) dfs(node.next);
}
dfs(head);
// console.log('ans',ans);
let result = ans[0];
let resultAns = result;
for (let i = 0; i < ans.length - 1; i++) {
result.next = ans[i + 1];
result.next.prev = result;
result.child = null;
result = result.next;
}
return resultAns;
};
附录
- dfs:递归写法 -> 深度优先遍历
- bfs:队列写法 -> 广度优先遍历