1,题目:
我们从二叉树的根节点 root 开始进行深度优先搜索。
在遍历中的每个节点处,我们输出 D 条短划线(其中 D 是该节点的深度),然后输出该节点的值。(如果节点的深度为 D,则其直接子节点的深度为 D + 1。根节点的深度为 0)。
如果节点只有一个子节点,那么保证该子节点为左子节点。
给出遍历输出 S,还原树并返回其根节点 root。
-
示例 1:
输入:“1-2–3--4-5–6--7”
输出:[1,2,5,3,4,6,7] -
示例 2:
输入:“1-2–3—4-5–6—7”
输出:[1,2,5,3,null,6,null,4,null,7] -
示例 3:
输入:“1-401–349—90–88”
输出:[1,401,null,349,88,90] -
提示:
原始树中的节点数介于 1 和 1000 之间。
每个节点的值介于 1 和 10 ^ 9 之间。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/recover-a-tree-from-preorder-traversal
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
2,算法说明:
1) 切割字符串,通过判断'-'的个数来算出第几层;通过strconv.Atoi来转换字符串到数字
2) 递归左右两边二叉树
3) 直接看代码,代码每一步都解释了,先看getDepth()函数,再看m()函数,
最后看recoverFromPreorder()函数
4) 觉得有启发的话,希望给个赞
3,代码
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
//主体函数
func recoverFromPreorder(S string) *TreeNode {
//如果字符串为空,则返回nil
if len(S) == 0 {
return nil
}
//调用迭代的函数,迭代大法好,二叉树的问题用迭代能解决一大半
//默认父亲层数是-1
_ , node := m(S , -1)
return node
}
//迭代函数,需要传入字符串,父亲层数
func m(S string , parent_depth int) (string , *TreeNode){
//如果字符串为空,就返回nil,也不用进行迭代了
if len(S) == 0 {
return S , nil
}
//通过截取字符串来解析当前是第几层,数值,剩余的字符串
d , n , St := getDepth(S)
//如果层数小于 && 等于 父亲层数,说明不要继续迭代了,需要返回
//这一步我认为是核心判断条件,关键靠这一步才能还原正确
if d <= parent_depth{
return S , nil
}
//根据数值new出一个二叉树
node := &TreeNode{Val:n}
//递归,得到二叉树左边,以及剩余的字符串
St , node.Left = m(St , d)
//递归,得到二叉树右边,以及剩余的字符串
St , node.Right = m(St , d)
return St , node
}
//通过截取字符串来解析当前是第几层,数值,剩余的字符串
func getDepth(S string) (int , int, string){
depth := 0
//通过判断'-'的个数,来算出第几层
for i := 0 ; i < len(S) ; i++{
if S[i] == '-'{
depth += 1
}else{
break
}
}
//转换字符串到数字,默认是截取到字符串最后一位,
//这样是为了避免传进来的字符串就没有包含'-'
endIdx := len(S)
for i := depth ; i < len(S) ; i++{
if S[i] == '-'{
endIdx = i
break
}
}
//基本不用考虑是否会转换出错
str , _ := strconv.Atoi(S[depth:endIdx])
//返回 第几层,数值,剩余的字符串
return depth , str , S[endIdx:len(S)]
}