展开多级双向链表

77 阅读1分钟

image.png

image.png

展开图:

image.png

代码:

  1. dfs 输入节点,输出能到达的最深处,也就是能往下就往下
  2. 代码实现就是,如果存在 child,就继续 dfs(child) ,得到子问题的 last 节点
  3. 然后就是节点指向改变,涉及当前节点,当前下一个节点,当前 child 节点,子问题 last 节点,防止丢失节点,合理使用变量保存之后的节点
  4. 当前节点的下一个节点可能为 nil 记得防止空指针
  5. 有 child ,last = next,防止当前的 last 就是最后一个节点,如果不是自然有 last = cur 覆盖回来
  6. 如果没有 child ,直接 last = cur
  7. 最后推动 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
}