面试题——根据二叉树后续遍历的数组,重建出整颗树并返回树的头结点
作者:互联网
已知一个搜索二叉树后续遍历的数组posArr,请根据posArr,重建出整棵树,返回树的头结点。
解决思路:
对于搜索二叉树BST,其每个节点的左子树的value都小于该节点的value,右子树的value都大于该节点的value。对二叉树进行后续遍历,对于每颗子树都是先遍历子树root节点的左子树,再遍历右子树,最后遍历该root节点所形成的序列。
采用递归建立的思想,先建立根节点,再建立左子树,和右子树。
例如对于vec = [2,4,3,6,8,7,5]
因为是后续遍历的结果,其左子树的所有节点小于根节点的值,右子树的节点大于根节点的值,并且根节点是最后一个被遍历到的节点。
其根节点value = 5; 左子树为:[2,4,3]; 右子树为[6,8,7]
然后递归的再对左子树和右子树建树:
左子树的根节点value为3,(左子树的)左子树为:[2]; 右子树为[4]
右子树的根节点value为7,(右子树的)左子树为:[6]; 右子树为[8]
代码如下:
process1\process2\process3
struct TreeNode
{
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};
int Rand(int min, int max)
{
srand(time(NULL));
return min + rand() % (max - min + 1);
}
TreeNode* createTree(int min, int max, int level, int N)
{
if (min > max || level > N)
{
return nullptr;
}
TreeNode* head = new TreeNode(Rand(min, max));
head->left = createTree(min, head->val - 1, level + 1, N);
head->right = createTree(head->val + 1, max, level + 1, N);
return head;
}
TreeNode* generateRandomBST(int min, int max, int N)
{
if (min > max)
{
return nullptr;
}
return createTree(min, max, 1, N);
}
void posOrderRecur(TreeNode* head, vector<int>& result)
{
if (head != nullptr)
{
posOrderRecur(head->left, result);
posOrderRecur(head->right, result);
result.push_back(head->val);
}
}
vector<int>& getBstPosVector(TreeNode* head)
{
vector<int>* result = new vector<int>();
//result->reserve(1000);
posOrderRecur(head, *result);
return *result;
}
bool isSameValueStructure(TreeNode* head1, TreeNode* head2)
{
if (head1 == nullptr && head2 != nullptr)
{
return false;
}
if (head1 != nullptr && head2 == nullptr)
{
return false;
}
if (head1 == nullptr && head2 == nullptr)
{
return true;
}
return head1->val == head2->val && isSameValueStructure(head1->left, head2->left) && isSameValueStructure(head1->right, head2->right);
}
string getSpace(int num)
{
string space = " ";
while (num--)
{
space.append(" ");
}
return space;
}
void printTreeInOrder(TreeNode* head, int height, string to, int len)
{
if (head == nullptr)
{
return;
}
printTreeInOrder(head->left, height + 1, "v", len);
string val = to + to_string(head->val) + to;
int lenM = val.length();
int lenL = (len - lenM) >> 2;
int LenR = len - lenM - lenM;
val = getSpace(lenL) + val + getSpace(LenR);
cout << getSpace(height * len) + val << endl;
printTreeInOrder(head->right, height + 1, "^", len);
}
void printTree(TreeNode* head)
{
cout << "Binary Tree : " << endl;
printTreeInOrder(head, 0, "H", 17);
cout << endl;
}
TreeNode* process1(vector<int>& vec, int L, int R)
{
if (L > R)
{
return nullptr;
}
TreeNode* head = new TreeNode(vec.at(R));
//Just one number
if (L == R)
{
return head;
}
//如果R左侧的数都小于R, [13245]
//如果R左侧的数都于大R, [321]
//如果R作为头节点,其他节点可能小于R,也可能大于R,如果有小于R的部分和大于R的部分,则小于R的部分一定在大于R的部分的右侧
// just <
// i最后的位置为R-1,M = R - 1
// just >
// M = L - 1
int M = L - 1;
for (int i = L; i < R; i++)
{
if (vec[i] < vec[R])
{
M = i; //从L到R-1范围上找小于R位置的数的最右侧的数的index
}
}
head->left = process1(vec, L, M);
head->right = process1(vec, M + 1, R - 1);
return head;
}
TreeNode* process2(vector<int>& vec, int L, int R)
{
if (L > R)
{
return nullptr;
}
TreeNode* head = new TreeNode(vec.at(R));
if (L == R)
{
return head;
}
int M = - 1;
for (int i = L; i < R; i++)
{
if (vec[i] < vec[R])
{
M = i;
}
}
if (M == -1)
{
head->right = process2(vec, L, R - 1);
}
else if (M == R - 1)
{
head->left = process2(vec, L, R - 1);
}
else
{
head->left = process2(vec, L, M);
head->right = process2(vec, M + 1, R - 1);
}
return head;
}
TreeNode* process3(vector<int>& vec, int L, int R)
{
if (L > R)
{
return nullptr;
}
TreeNode* head = new TreeNode(vec.at(R));
if (L == R)
{
return head;
}
int M = L - 1;
int left = L;
int right = R - 1;
while (left <= right)
{
int mid = left + ((right - left) >> 1);
if (vec[mid] < vec[R])
{
M = mid;
left = mid + 1;
}
else
{
right = mid - 1;
}
}
head->left = process3(vec, L, M);
head->right = process3(vec, M + 1, R - 1);
return head;
}
TreeNode* posVecToBST1(vector<int> vec)
{
return process1(vec, 0, vec.size() - 1);
}
TreeNode* posVecToBST2(vector<int> vec)
{
return process2(vec, 0, vec.size() - 1);
}
TreeNode* posVecToBST3(vector<int> vec)
{
return process3(vec, 0, vec.size() - 1);
}
void test()
{
TreeNode* head = generateRandomBST(0, 12, 4);
vector<int> result = std::move(getBstPosVector(head));
//vector<int> result1 = std::move(getBstPosVector(posVecToBST1(result)));
//vector<int> result2 = std::move(getBstPosVector(posVecToBST3(result)));
if (!isSameValueStructure(head, posVecToBST1(result)) || !isSameValueStructure(head, posVecToBST3(result)))
{
cout << "error" << endl;
}
else
{
cout << "success" << endl;
}
}
//bool IsPosOrderRecur(vector<int>& result, int length)
//{
// if (result.size() == 0 || length <= 0)
// {
// return true;
// }
//
// int rootValue = result[length - 1];
// int leftIndex;
// int rightIndex;
// int i = 0;
// while (i < length && result[i] < rootValue)
// {
// i++;
// }
// leftIndex = i;
// rightIndex = length - 1 - leftIndex;
// for (; i < length; i++)
// {
// if (result[i] < rootValue)
// {
// return false;
// }
// }
// bool left = true;
// bool right = true;
// left = IsPosOrderRecur(result, leftIndex);
// right = IsPosOrderRecur(result + leftIndex, rightIndex);
//}
//int main()
//{
// test();
// return 0;
//
//}
bool IsPostOrder(int* sequence, int length)
{
if (sequence == NULL || length <= 0)
{
return true;
}
/*if (sequence != NULL && length > 0)
{*/
int rootValue = sequence[length - 1];
int leftLength, rightLength;
int i = 0;
while (i < length && sequence[i] < rootValue)
{
i++;
}
leftLength = i;
rightLength = length - leftLength - 1;
for (; i < length; i++)//向右子树找有没有不符合二叉搜索树性质的。
{
if (sequence[i] < rootValue)
{
return false;
}
}
bool left = true, right = true;//left和right初始化为true;
left = IsPostOrder(sequence, leftLength);
right = IsPostOrder(sequence + leftLength, rightLength);
return left && right;
//}
}
int main()
{
int sequence[] = { 5,7,6,9,11,10,8 };
if (IsPostOrder(sequence, sizeof(sequence) / sizeof(sequence[0])))
{
cout << "是二叉搜索树的后序遍历" << endl;
}
else
{
cout << "不是二叉搜索树的后序遍历" << endl;
}
return 0;
}
标签:面试题,return,int,整颗,head,二叉树,TreeNode,left,vec 来源: https://blog.csdn.net/CLZHIT/article/details/110418779