剑指Offer题目如下:
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
前序遍历 遍历顺序是:A->B->C
中序遍历 遍历顺序是 :B->A->C
前序代码:
traverse(node : TreeNode)
{if node == null{
return null
}
访问该节点 按照该例子就是把node.val加进前序数组
traverse(node.left)
traverse(node.right)
}
}
中序代码:
traverse(node : TreeNode)
{if node == null{
return null
}
traverse(node.left)
访问该节点 按照该例子就是把node.val加进中序数组
traverse(node.right)
}
}
综上可以知道,如果给出的是前序遍历数组,他会先遍历每个小二叉树顶点,一直到最左边,所以用来分割成左右子树需要用前序遍历的每个节点;如果给出的是中序遍历数组,你可以利用前序遍历中得到的节点,找到他在中序遍历的位置,就可以把中序遍历数组分成左右两个子树数组了。我们使用递归方法,一步步把数组才分成左右子树分到不同的树节点。
下面是swift实现代码
import Foundation
public class TreeNode {
public var left : TreeNode?
public var right : TreeNode?
public var val : Int = 0
public func initWithValue(_ value : Int) {
self.val = value
self.left = nil
self.right = nil
}
}
class Solution {
func RecreateBinaryTree(by pre : [Int] , by mid : [Int] ) -> TreeNode? {
return buildTree(pre: pre, preStart: 0 , preEnd: pre.count - 1 , mid: mid, inStart: 0, inEnd: mid.count - 1)
}
func buildTree(pre : [Int] , preStart : Int, preEnd : Int , mid : [Int] , inStart : Int , inEnd : Int) -> TreeNode? {
if preStart > preEnd {
return nil
}
let value = pre[preStart]
let node = TreeNode()
node.initWithValue(value)
var index = inStart
while mid[index] != value {
index += 1
}
node.left = buildTree(pre: pre, preStart: preStart + 1, preEnd:preStart + inStart - index, mid: mid, inStart: inStart, inEnd: index-1)
node.right = buildTree(pre: pre, preStart:preStart + inStart - index + 1 , preEnd: preEnd, mid: mid, inStart: index + 1, inEnd: inEnd)
return node
}
}
来看看这句
node.left = buildTree(pre: pre, preStart: preStart + 1, preEnd:preStart + inStart - index, mid: mid, inStart: inStart, inEnd: index-1)
这个函数里面的参数首先由pre的数组以及其开始位置和结束位置和mid的数组以及其开始位置和结束位置构成 。pre数组就是用来提供根节点的,所以preStart+1传进去就行,但是知道根节点后,我们怎么知道pre数组几位到几位是给left的呢,这时候就要看mid数组了,我们需要用index去找到终点嘛,这个index偏移了多少位才找到中间节点,而这个多少位就是用来说明有多少个属于左子树的,我们就可以使用inStart - index来得出左子树的个数,再加上preStart就可以知道哪段范围在pre数组是属于左子树的。
node.right就跟上面思路一样。