#LeetCode每日一题【链表专题】
- 扁平化多级双向链表
https://leetcode-cn.com/problems/flatten-a-multilevel-doubly-linked-list/ - 分析
题目描述得比较复杂,但其实理解了之后,大致意思就是优先遍历子集链表,在往后遍历;基本拿到手就能想到使用递归,判断该节点有无child,有则递归调用自身,没有则直接向下。当递归完之后,在将结果插入之前的链表即可。 - 实现
public Node flatten(Node head) {
Node node = head, next;
while (node != null) {
next = node.next;
if (node.child != null) {
Node child = flatten(node.child);
// 找到child的最后一个元素
Node temp = child;
while (temp.next != null) {
temp = temp.next;
}
// 将child插入node后面
temp.next = next;
if (next != null) {
// next可能为空,及不再需要维护其prev
next.prev = temp;
}
node.next = child;
child.prev = node;
// 断开孩子关系
node.child = null;
}
node = next;
}
return head;
}
LeetCode耗时:0ms
- 优化
后面看了下题解,可以把上面每次寻找链表尾节点给去掉,另启用一个方法使用递归,返回的是每次处理完链表的最后一个节点
public Node flatten02(Node head) {
// 优化:重新起一个方法开启递归,使其返回处理后的最后一个节点,利于拼接;;避免向上面一样,从头开始找最后一个节点
dfs(head);
return head;
}
private Node dfs(Node head) {
Node node = head, next, last = null;
while (node != null) {
next = node.next;
if (node.child != null) {
Node childLast = dfs(node.child);
// childLast是child的最后一个元素
// 将child插入node后面
childLast.next = next;
if (next != null) {
// next可能为空,及不再需要维护其prev
next.prev = childLast;
}
node.next = node.child;
node.child.prev = node;
// 处理完之后,对于拼接上的链表最后一个节点是childLast
last = childLast;
// 断开孩子关系
node.child = null;
} else {
last = node;
}
node = next;
}
return last;
}
思路都是一样的,只不过需要处理下找到链表的尾节点再返回
LeetCode耗时:0ms
-
总结
类似这种涉及深层次的遍历,考虑使用递归的方式处理,思考递归之后会返回什么,拿到了返回结果,需要跟当前元素做些什么操作。最后再加注意点细节处理就好。 -
最后
LeetCode链表专题,已完成31。下个月开辟下一个专题,二叉树~