题意:
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true
,否则返回 false
。假设输入的数组的任意两个数字都互不相同。
思想:
1. 根据二叉搜索树的性质:根节点的大于左子树的所有节点,小于右子树的所有节点
2. 后序遍历的数组特点:根节点的左子树和右子树都在根节点之前,左子树在右子树的节点之前,根节点在最后
根据以上两个性质,对于每个搜索树而言,后续遍历的数组结构满足前面的一段大于根节点,后段满足小于根节点;利用递归需要对根节点的左子树和右子树做同样的判断
实现:
class Solution {
public:
bool verifyPostorder(vector<int>& postorder) {
if(postorder.empty()) return true;
return verifyPostorder(postorder,0,postorder.size()-1);
}
private:
bool verifyPostorder(vector<int>& postorder,int start,int end){
if(start >= end) return true;
int p = start;
while(postorder[p] < postorder[end]) p++;
int leftTreeEnd = p;
while(postorder[p] > postorder[end]) p++;
return p == end && verifyPostorder(postorder,start,leftTreeEnd-1) && verifyPostorder(postorder,leftTreeEnd,end-1);
}
};
题意:
输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
思想:
前序遍历数组特点:根节点、左子树、右子树,每个子树的遍历顺序同样满足前序遍历顺序。
中序遍历数组特点:左子树、根节点、右子树,每个子树的遍历顺序同样满足中序遍历顺序。
3
/ \
9 20
\ / \
4 15 7前序:3 9 4 20 15 7
中序:9 4 3 15 20 7
前序遍历的第一个节点是根节点,只要找到根节点在中序遍历中的位置,在根节点之前被访问的节点都位于左子树,在根节点之后被访问的节点都位于右子树,由此可知左子树和右子树分别有多少个节点。然后递归构造左右子树,递归的终止条件就是当前的节点为叶子节点。
实现:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
if(preorder.empty()) return nullptr;
unordered_map<int,int> _allNodeMap;//利用map,快速的访问索引
for(int i = 0 ;i < inorder.size();i++){
_allNodeMap[inorder[i]] = i;
}
return buildTree(preorder,0,preorder.size()-1,inorder,0,inorder.size()-1,_allNodeMap);
}
TreeNode* buildTree(vector<int>& preorder,int preorderStart,int preorderEnd,vector<int>& inorder,int inorderStart,int inorderEnd,unordered_map<int,int>& map){
if(preorderStart > preorderEnd) return nullptr;
//获得当前的root值
int rootVal = preorder[preorderStart];
TreeNode* root = new TreeNode(rootVal);
if(preorderStart == preorderEnd)//当前只有一个数据,没有左右节点
return root;
else{
//获得当前的root的索引
int rootIndex = map[rootVal];
//计算当前左右子树节点的数目
int leftNode = rootIndex - inorderStart;
int rightNode = inorderEnd - rootIndex;
TreeNode* leftTree = buildTree(preorder,preorderStart+1,preorderStart+leftNode,inorder,inorderStart,inorderStart+leftNode,map);
TreeNode* rightTree = buildTree(preorder,preorderStart+leftNode+1,preorderEnd,inorder,rootIndex+1,inorderEnd,map);
root->left = leftTree;
root->right = rightTree;
return root;
}
}
};