展开图:
代码:
- dfs 输入节点,输出能到达的最深处,也就是能往下就往下
- 代码实现就是,如果存在 child,就继续 dfs(child) ,得到子问题的 last 节点
- 然后就是节点指向改变,涉及当前节点,当前下一个节点,当前 child 节点,子问题 last 节点,防止丢失节点,合理使用变量保存之后的节点
- 当前节点的下一个节点可能为 nil 记得防止空指针
- 有 child ,last = next,防止当前的 last 就是最后一个节点,如果不是自然有 last = cur 覆盖回来
- 如果没有 child ,直接 last = cur
- 最后推动 for 循环,cur = next,当然这里的 next 是之前就存储的,因为 cur.Next 可能已经换了,当然其实直接让 cur = cur.Next 也无所谓,顶多多走两步路罢了
/**
* Definition for a Node.
* type Node struct {
* Val int
* Prev *Node
* Next *Node
* Child *Node
* }
*/
func dfs(node *Node) (last *Node) {
cur := node
for cur != nil {
next := cur.Next
// 如果有子节点,那么首先处理子节点
if cur.Child != nil {
childLast := dfs(cur.Child)
// next = cur.Next
// 将 node 与 child 相连
cur.Next = cur.Child
cur.Child.Prev = cur
// 如果 next 不为空,就将 last 与 next 相连
if next != nil {
childLast.Next = next
next.Prev = childLast
}
// 将 child 置为空
cur.Child = nil
last = childLast
} else {
last = cur
}
cur = next
}
return
}
func flatten(root *Node) *Node {
dfs(root)
return root
}