mirror of
https://github.com/youngyangyang04/leetcode-master.git
synced 2025-07-07 15:45:40 +08:00
update 0106.从中序与后序遍历序列构造二叉树: 更新 go 代码
This commit is contained in:
@ -34,7 +34,7 @@
|
||||
|
||||
## 思路
|
||||
|
||||
首先回忆一下如何根据两个顺序构造一个唯一的二叉树,相信理论知识大家应该都清楚,就是以 后序数组的最后一个元素为切割点,先切中序数组,根据中序数组,反过来在切后序数组。一层一层切下去,每次后序数组最后一个元素就是节点元素。
|
||||
首先回忆一下如何根据两个顺序构造一个唯一的二叉树,相信理论知识大家应该都清楚,就是以 后序数组的最后一个元素为切割点,先切中序数组,根据中序数组,反过来再切后序数组。一层一层切下去,每次后序数组最后一个元素就是节点元素。
|
||||
|
||||
如果让我们肉眼看两个序列,画一棵二叉树的话,应该分分钟都可以画出来。
|
||||
|
||||
@ -236,7 +236,7 @@ private:
|
||||
vector<int> leftPostorder(postorder.begin(), postorder.begin() + leftInorder.size());
|
||||
vector<int> rightPostorder(postorder.begin() + leftInorder.size(), postorder.end());
|
||||
|
||||
// 一下为日志
|
||||
// 以下为日志
|
||||
cout << "----------" << endl;
|
||||
|
||||
cout << "leftInorder :";
|
||||
@ -275,7 +275,7 @@ public:
|
||||
};
|
||||
```
|
||||
|
||||
**此时应该发现了,如上的代码性能并不好,应为每层递归定定义了新的vector(就是数组),既耗时又耗空间,但上面的代码是最好理解的,为了方便读者理解,所以用如上的代码来讲解。**
|
||||
**此时应该发现了,如上的代码性能并不好,因为每层递归定义了新的vector(就是数组),既耗时又耗空间,但上面的代码是最好理解的,为了方便读者理解,所以用如上的代码来讲解。**
|
||||
|
||||
下面给出用下标索引写出的代码版本:(思路是一样的,只不过不用重复定义vector了,每次用下标索引来分割)
|
||||
|
||||
@ -569,7 +569,7 @@ tree2 的前序遍历是[1 2 3], 后序遍历是[3 2 1]。
|
||||
|
||||
之前我们讲的二叉树题目都是各种遍历二叉树,这次开始构造二叉树了,思路其实比较简单,但是真正代码实现出来并不容易。
|
||||
|
||||
所以要避免眼高手低,踏实的把代码写出来。
|
||||
所以要避免眼高手低,踏实地把代码写出来。
|
||||
|
||||
我同时给出了添加日志的代码版本,因为这种题目是不太容易写出来调一调就能过的,所以一定要把流程日志打出来,看看符不符合自己的思路。
|
||||
|
||||
@ -728,25 +728,33 @@ class Solution:
|
||||
* Right *TreeNode
|
||||
* }
|
||||
*/
|
||||
var (
|
||||
hash map[int]int
|
||||
)
|
||||
func buildTree(inorder []int, postorder []int) *TreeNode {
|
||||
if len(inorder)<1||len(postorder)<1{return nil}
|
||||
//先找到根节点(后续遍历的最后一个就是根节点)
|
||||
nodeValue:=postorder[len(postorder)-1]
|
||||
//从中序遍历中找到一分为二的点,左边为左子树,右边为右子树
|
||||
left:=findRootIndex(inorder,nodeValue)
|
||||
//构造root
|
||||
root:=&TreeNode{Val: nodeValue,
|
||||
Left: buildTree(inorder[:left],postorder[:left]),//将后续遍历一分为二,左边为左子树,右边为右子树
|
||||
Right: buildTree(inorder[left+1:],postorder[left:len(postorder)-1])}
|
||||
hash = make(map[int]int)
|
||||
for i, v := range inorder { // 用map保存中序序列的数值对应位置
|
||||
hash[v] = i
|
||||
}
|
||||
// 以左闭右闭的原则进行切分
|
||||
root := rebuild(inorder, postorder, len(postorder)-1, 0, len(inorder)-1)
|
||||
return root
|
||||
}
|
||||
func findRootIndex(inorder []int,target int) (index int){
|
||||
for i:=0;i<len(inorder);i++{
|
||||
if target==inorder[i]{
|
||||
return i
|
||||
}
|
||||
// rootIdx表示根节点在后序数组中的索引,l, r 表示在中序数组中的前后切分点
|
||||
func rebuild(inorder []int, postorder []int, rootIdx int, l, r int) *TreeNode {
|
||||
if l > r { // 说明没有元素,返回空树
|
||||
return nil
|
||||
}
|
||||
return -1
|
||||
if l == r { // 只剩唯一一个元素,直接返回
|
||||
return &TreeNode{Val : inorder[l]}
|
||||
}
|
||||
rootV := postorder[rootIdx] // 根据后序数组找到根节点的值
|
||||
rootIn := hash[rootV] // 找到根节点在对应的中序数组中的位置
|
||||
root := &TreeNode{Val : rootV} // 构造根节点
|
||||
// 重建左节点和右节点
|
||||
root.Left = rebuild(inorder, postorder, rootIdx-(r-rootIn)-1, l, rootIn-1)
|
||||
root.Right = rebuild(inorder, postorder, rootIdx-1, rootIn+1, r)
|
||||
return root
|
||||
}
|
||||
```
|
||||
|
||||
@ -761,22 +769,27 @@ func findRootIndex(inorder []int,target int) (index int){
|
||||
* Right *TreeNode
|
||||
* }
|
||||
*/
|
||||
var (
|
||||
hash map[int]int
|
||||
)
|
||||
func buildTree(preorder []int, inorder []int) *TreeNode {
|
||||
if len(preorder)<1||len(inorder)<1{return nil}
|
||||
left:=findRootIndex(preorder[0],inorder)
|
||||
root:=&TreeNode{
|
||||
Val: preorder[0],
|
||||
Left: buildTree(preorder[1:left+1],inorder[:left]),
|
||||
Right: buildTree(preorder[left+1:],inorder[left+1:])}
|
||||
hash = make(map[int]int, len(inorder))
|
||||
for i, v := range inorder {
|
||||
hash[v] = i
|
||||
}
|
||||
root := build(preorder, inorder, 0, 0, len(inorder)-1) // l, r 表示构造的树在中序遍历数组中的范围
|
||||
return root
|
||||
}
|
||||
func findRootIndex(target int,inorder []int) int{
|
||||
for i:=0;i<len(inorder);i++{
|
||||
if target==inorder[i]{
|
||||
return i
|
||||
}
|
||||
func build(pre []int, in []int, root int, l, r int) *TreeNode {
|
||||
if l > r {
|
||||
return nil
|
||||
}
|
||||
return -1
|
||||
rootVal := pre[root] // 找到本次构造的树的根节点
|
||||
index := hash[rootVal] // 根节点在中序数组中的位置
|
||||
node := &TreeNode {Val: rootVal}
|
||||
node.Left = build(pre, in, root + 1, l, index-1)
|
||||
node.Right = build(pre, in, root + (index-l) + 1, index+1, r)
|
||||
return node
|
||||
}
|
||||
```
|
||||
|
||||
|
Reference in New Issue
Block a user