1028. 从先序遍历还原二叉树

87 阅读1分钟

题目:
我们从二叉树的根节点 root 开始进行深度优先搜索。

在遍历中的每个节点处,我们输出 D 条短划线(其中 D 是该节点的深度),然后输出该节点的值。(如果节点的深度为 D,则其直接子节点的深度为 D + 1。根节点的深度为 0)。

如果节点只有一个子节点,那么保证该子节点为左子节点。

给出遍历输出 S,还原树并返回其根节点 root

算法:

方法一:dfs+模拟
注意边界条件:

  1. 单个数字的位数不只一位
  2. 只有左子树的情况rightChildStart > right
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func recoverFromPreorder(traversal string) *TreeNode {
    var dfs func(left, right, depth int) *TreeNode
    dfs = func(left, right, depth int) *TreeNode {
        
        if left > right {
            return nil
        }
        // 一个数字位数可能超过一位
        numEnd := left
        for numEnd <= right {
            if traversal[numEnd] == '-' {
                break
            }
            numEnd ++
        }
        // 获取当前的数字
        v, _ := strconv.Atoi(traversal[left:numEnd])
        depth ++
        node := TreeNode{
            Val: v,
        }
        leftChildStart := numEnd + depth 
        rightChildStart := leftChildStart
        cnt := 0
        for ; rightChildStart <= right; rightChildStart ++ {
            if traversal[rightChildStart] != '-' {
                if cnt == depth {
                    break
                } else {
                    cnt = 0
                }
                
            } else {
                cnt ++
            }
        }

        leftChildEnd := rightChildStart - depth - 1
        // “如果节点只有一个子节点,那么保证该子节点为左子节点”
        // 只有左子树
        if rightChildStart > right {
            leftChildEnd = right
        }
        node.Left = dfs(leftChildStart, leftChildEnd, depth)
        node.Right = dfs(rightChildStart, right, depth)
        return &node
    }
    return dfs(0, len(traversal) - 1, 0)
}

方法二: 迭代
如何想到用栈实现呢?栈的深度 > 当前的level数就出栈。出栈时机和栈的深度的关系。

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func recoverFromPreorder(traversal string) *TreeNode {
    stack := make([]*TreeNode, 0)
    for i := 0; i < len(traversal);  {
        // 计算curlevel
        curlevel := 0
        for i < len(traversal) && traversal[i] == '-' {
            i ++
            curlevel ++
        }
        // 计算当前数字
        numStart := i 
        for i < len(traversal) && traversal[i] != '-' {
            i ++
        }
        val, _ := strconv.Atoi(traversal[numStart:i])
        node := &TreeNode{Val: val}

        n := len(stack)
        if n == 0 {
            stack = append(stack, node)
            continue
        }
        // stack size > curlevel ,出栈
        if n > curlevel {
            
            stack = stack[:curlevel]
        }

        n = len(stack)
        // 创建新节点,赋值给stack最后元素
        if stack[n - 1].Left == nil {
            stack[n - 1].Left = node
        } else {
            stack[n - 1].Right = node
        }
        // 新节点入栈
        stack = append(stack, node)
    }
    return stack[0]
}