题目描述
样例描述
思路
方法一:递归 + 迭代 O(n^2)
- 没孩子结点就一直next,如果有孩子结点,就先存储当前结点的下一个,然后不断递归(将孩子部分先展平),随后拼接当前结点和展平后的部分,并将当前结点的孩子指针设置为null,然后寻找展平部分的最后一个结点与原始当前结点的下一个结点进行拼接。 最后将当前结点设置为原始的下一个,准备下一轮迭代。
方法二:对方法一的优化:额外写递归函数 O(n)
- 方法一中由于每次是从head.child开始递归,又要每一次再次遍历寻找展平部分的尾结点。这里最坏情况复杂度是平方。
- 单独写递归函数,每次直接返回展平后的"尾结点",使得找尾结点的部分不会在每一层出现,可以达到O(n)
递归拼接顺序如下:
方法三: 迭代 迭代的拼接顺序与递归不同,是一段一段进行的,区别如下:
- 让head从最开始一直走,只要child不为空,就先迭代拼接处理完child层,然后继续往后,碰到有child就拼接。(虽然head会越遍历越长,因为不断拼接了child层,但是对每个结点只会访问常数次)
代码
方法一:
class Solution {
public Node flatten(Node head) {
Node dummy = new Node(-1);
dummy.next = head;
while (head != null) {
if (head.child == null) {
head = head.next;
} else {
Node nextN = head.next;
Node flatnode = flatten(head.child);
head.next = flatnode;
flatnode.prev = head;
head.child = null;
while (head.next != null) {
head = head.next;
}
head.next = nextN;
if (nextN != null)
nextN.prev = head;
head = nextN;
}
}
return dummy.next;
}
}
方法二:优化递归
class Solution {
public Node flatten(Node head) {
dfs(head);
return head;
}
public Node dfs(Node head) {
Node last = head;
while (head != null) {
if (head.child == null) {
last = head;
head = head.next;
} else {
Node nextN = head.next;
Node lastChild = dfs(head.child);
head.next = head.child;
head.child.prev = head;
head.child = null;
lastChild.next = nextN;
if (nextN != null) {
nextN.prev = lastChild;
}
head = lastChild;
}
}
return last;
}
}
方法三:
class Solution {
public Node flatten(Node head) {
Node dummy = new Node(-1);
dummy.next = head;
while (head != null) {
if (head.child != null) {
Node t = head.next;
Node child = head.child;
head.next = child;
child.prev = head;
head.child = null;
Node last = child;
while (last.next != null) {
last = last.next;
}
last.next = t;
if (t != null) {
t.prev = last;
}
}
head = head.next;
}
return dummy.next;
}
}
|