题目:
我们从二叉树的根节点 root 开始进行深度优先搜索。
在遍历中的每个节点处,我们输出 D 条短划线(其中 D 是该节点的深度),然后输出该节点的值。(如果节点的深度为 D,则其直接子节点的深度为 D + 1。根节点的深度为 0)。
如果节点只有一个子节点,那么保证该子节点为左子节点。
给出遍历输出 S,还原树并返回其根节点 root。
算法:
方法一:dfs+模拟
注意边界条件:
- 单个数字的位数不只一位
- 只有左子树的情况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]
}