mirror of
https://github.com/youngyangyang04/leetcode-master.git
synced 2025-07-08 00:43:04 +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> leftPostorder(postorder.begin(), postorder.begin() + leftInorder.size());
|
||||||
vector<int> rightPostorder(postorder.begin() + leftInorder.size(), postorder.end());
|
vector<int> rightPostorder(postorder.begin() + leftInorder.size(), postorder.end());
|
||||||
|
|
||||||
// 一下为日志
|
// 以下为日志
|
||||||
cout << "----------" << endl;
|
cout << "----------" << endl;
|
||||||
|
|
||||||
cout << "leftInorder :";
|
cout << "leftInorder :";
|
||||||
@ -275,7 +275,7 @@ public:
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
**此时应该发现了,如上的代码性能并不好,应为每层递归定定义了新的vector(就是数组),既耗时又耗空间,但上面的代码是最好理解的,为了方便读者理解,所以用如上的代码来讲解。**
|
**此时应该发现了,如上的代码性能并不好,因为每层递归定义了新的vector(就是数组),既耗时又耗空间,但上面的代码是最好理解的,为了方便读者理解,所以用如上的代码来讲解。**
|
||||||
|
|
||||||
下面给出用下标索引写出的代码版本:(思路是一样的,只不过不用重复定义vector了,每次用下标索引来分割)
|
下面给出用下标索引写出的代码版本:(思路是一样的,只不过不用重复定义vector了,每次用下标索引来分割)
|
||||||
|
|
||||||
@ -569,7 +569,7 @@ tree2 的前序遍历是[1 2 3], 后序遍历是[3 2 1]。
|
|||||||
|
|
||||||
之前我们讲的二叉树题目都是各种遍历二叉树,这次开始构造二叉树了,思路其实比较简单,但是真正代码实现出来并不容易。
|
之前我们讲的二叉树题目都是各种遍历二叉树,这次开始构造二叉树了,思路其实比较简单,但是真正代码实现出来并不容易。
|
||||||
|
|
||||||
所以要避免眼高手低,踏实的把代码写出来。
|
所以要避免眼高手低,踏实地把代码写出来。
|
||||||
|
|
||||||
我同时给出了添加日志的代码版本,因为这种题目是不太容易写出来调一调就能过的,所以一定要把流程日志打出来,看看符不符合自己的思路。
|
我同时给出了添加日志的代码版本,因为这种题目是不太容易写出来调一调就能过的,所以一定要把流程日志打出来,看看符不符合自己的思路。
|
||||||
|
|
||||||
@ -728,25 +728,33 @@ class Solution:
|
|||||||
* Right *TreeNode
|
* Right *TreeNode
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
|
var (
|
||||||
|
hash map[int]int
|
||||||
|
)
|
||||||
func buildTree(inorder []int, postorder []int) *TreeNode {
|
func buildTree(inorder []int, postorder []int) *TreeNode {
|
||||||
if len(inorder)<1||len(postorder)<1{return nil}
|
hash = make(map[int]int)
|
||||||
//先找到根节点(后续遍历的最后一个就是根节点)
|
for i, v := range inorder { // 用map保存中序序列的数值对应位置
|
||||||
nodeValue:=postorder[len(postorder)-1]
|
hash[v] = i
|
||||||
//从中序遍历中找到一分为二的点,左边为左子树,右边为右子树
|
}
|
||||||
left:=findRootIndex(inorder,nodeValue)
|
// 以左闭右闭的原则进行切分
|
||||||
//构造root
|
root := rebuild(inorder, postorder, len(postorder)-1, 0, len(inorder)-1)
|
||||||
root:=&TreeNode{Val: nodeValue,
|
|
||||||
Left: buildTree(inorder[:left],postorder[:left]),//将后续遍历一分为二,左边为左子树,右边为右子树
|
|
||||||
Right: buildTree(inorder[left+1:],postorder[left:len(postorder)-1])}
|
|
||||||
return root
|
return root
|
||||||
}
|
}
|
||||||
func findRootIndex(inorder []int,target int) (index int){
|
// rootIdx表示根节点在后序数组中的索引,l, r 表示在中序数组中的前后切分点
|
||||||
for i:=0;i<len(inorder);i++{
|
func rebuild(inorder []int, postorder []int, rootIdx int, l, r int) *TreeNode {
|
||||||
if target==inorder[i]{
|
if l > r { // 说明没有元素,返回空树
|
||||||
return i
|
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
|
* Right *TreeNode
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
|
var (
|
||||||
|
hash map[int]int
|
||||||
|
)
|
||||||
func buildTree(preorder []int, inorder []int) *TreeNode {
|
func buildTree(preorder []int, inorder []int) *TreeNode {
|
||||||
if len(preorder)<1||len(inorder)<1{return nil}
|
hash = make(map[int]int, len(inorder))
|
||||||
left:=findRootIndex(preorder[0],inorder)
|
for i, v := range inorder {
|
||||||
root:=&TreeNode{
|
hash[v] = i
|
||||||
Val: preorder[0],
|
}
|
||||||
Left: buildTree(preorder[1:left+1],inorder[:left]),
|
root := build(preorder, inorder, 0, 0, len(inorder)-1) // l, r 表示构造的树在中序遍历数组中的范围
|
||||||
Right: buildTree(preorder[left+1:],inorder[left+1:])}
|
|
||||||
return root
|
return root
|
||||||
}
|
}
|
||||||
func findRootIndex(target int,inorder []int) int{
|
func build(pre []int, in []int, root int, l, r int) *TreeNode {
|
||||||
for i:=0;i<len(inorder);i++{
|
if l > r {
|
||||||
if target==inorder[i]{
|
return nil
|
||||||
return i
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
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