提供了一种特殊类型的树,其中所有树叶都标有L
,其他树标记为N
。每个节点可以有0个或最多2个节点。给出了树的前序遍历。
给出一个算法来从这个遍历中构建树。
答案 0 :(得分:16)
这是预订序遍历算法:
Preorder(T)
if (T is not null)
print T.label
Preorder(T.left)
Preorder(T.right)
让我们尝试找一个输入NNLLNL
的算法。
显然首先打印根标签。所以你知道root有标签N
。现在算法在左子树上进行递归。根据输入,这也是N
。递归到左边的子树,即L
。现在你必须回溯,因为你已经到了一片叶子。输入中的下一个位置也是L
,因此当前节点有一个标有L
的正确子项。回溯一次。再次回溯,因为您已添加当前节点的所有子节点(最多2个子节点)。现在你又回到了原点。你必须走对,因为你已经离开了。根据输入,这是N
。因此,根的正确子项为N
。左边的孩子将是L
。这是你的树:
N
/ \
N N
/ \ /
L L L
请注意,解决方案不一定是唯一的,但这将为您提供可能的解决方案。
伪代码:
k = 0
input = ... get preorder traversal vector from user ...
Reconstruct(T)
if input[k] == N
T = new node with label N
k = k + 1
Reconstruct(T.left)
Reconstruct(T.right)
else
T = new node with label L
T.left = T.right = null
k = k + 1
使用空节点调用。
后续问题:给定包含不同节点标签的二叉树的预订和顺序遍历,您如何才能唯一地重建树?
答案 1 :(得分:0)
这是我的golang版本,用于解决leetcode中关于树的许多问题。
// NewPreorderTree returns preorder tree relate to nums, nums must has not Ambiguity.
// -1 in nums represents child is null.
//
// Example 1:
// Input: [1, 2, 3]
// Generate:
// 1
// /
// 2
// /
// 3
//
// Example 2:
// Input: [1, 2, -1, -1, 3] or [1, 2, -1, -1, 3, -1, -1]
// Generate:
// 1
// / \
// 2 3
func NewPreorderTree(nums ...int) *TreeNode {
return (&preorderTree{nums}).constructTree()
}
type preorderTree struct {
nums []int
}
func (p *preorderTree) constructTree() *TreeNode {
if len(p.nums) == 0 {
return nil
}
if p.nums[0] == -1 {
p.nums = p.nums[1:]
return nil
}
root := &TreeNode{Val: p.nums[0]}
p.nums = p.nums[1:]
root.Left = p.constructTree()
root.Right = p.constructTree()
return root
}