思路和题1143一样,只不过寻找时不能再依靠BST的性质来判断左右子树,可以在构建树时将 该节点是父节点的左子树或是右子树 这一信息保存在每个节点中。
思路一样,但这题卡了很久…因为遗漏了一个细节,回溯时我只考虑了寻找父节点的左子树或右子树,而没有考虑到父节点就可能是我们要寻找的u或v。一直出现段错误,题1143也出现段错误,是因为没有考虑u,v相等且都为根节点的情况。总之,使用指针很容易由于考虑不周全而出现段错误。最后发现错误的方法是,自己写了一个样例,不停的测试。
考试时出现段错误或部分样例不通过的情况下,首先读题,再看代码,然后自己举例测试。总之要镇定,不要放弃。
#include<stdio.h>
#include<stdlib.h>
typedef struct Node* Tree;
struct Node
{
int key;
Tree left;
Tree right;
Tree parent;
bool isLeft;
};
int preorder[10005], inorder[10005];
Tree construct(int s1, int e1, int s2, int e2, Tree parent, bool isLeft)
{
if (s1 > e1 || s2 > e2) return NULL;
if (s1 == e1 || s2 == e2)
{
Tree T = (Tree)malloc(sizeof(Node));
T->key = preorder[s1];
T->parent = parent;
T->isLeft = isLeft;
T->left = T->right = NULL;
return T;
}
else
{
Tree T = (Tree)malloc(sizeof(Node));
T->key = preorder[s1];
T->parent = parent;
T->isLeft = isLeft;
T->left = T->right = NULL;
int index = s2;
for (index = s2; index <= e2; index++)
{
if (inorder[index] == T->key)
{
break;
}
}
T->left = construct(s1 + 1, s1 + index - s2, s2, index - 1, T, true);
T->right = construct(s1 + index - s2 + 1, e1, index + 1, e2, T, false);
return T;
}
}
Tree find(int x, Tree T)
{
if (T == NULL) return NULL;
if (T->key == x) return T;
Tree leftResult = find(x, T->left);
if (leftResult != NULL) return leftResult;
Tree rightResult = find(x, T->right);
if (rightResult != NULL) return rightResult;
return NULL;
}
int getLCA(Tree T, int U, int V)
{
if (T->key == U) return U;
if (T->key == V) return V;
Tree uptr = find(U, T); // 不为空,因为前面已经判断U是存在的
if (find(V, uptr) != NULL) return U; // U下面能够找到V
Tree upptr = uptr->parent; // U的父节点不为空
while (upptr != NULL)
{
if (upptr->key == V)
{
return upptr->key;
}
if (uptr->isLeft == true)
{
Tree tmp = find(V, upptr->right);
if (tmp != NULL) return upptr->key;
}
if (uptr->isLeft == false)
{
Tree tmp = find(V, upptr->left);
if (tmp != NULL) return upptr->key;
}
uptr = upptr;
upptr = uptr->parent;
}
}
int main()
{
int M, N;
scanf("%d%d", &M, &N);
for (int i = 0; i < N; i++)
{
scanf("%d", &inorder[i]);
}
for (int i = 0; i < N; i++)
{
scanf("%d", &preorder[i]);
}
Tree T = construct(0, N - 1, 0, N - 1, NULL, true);
for (int i = 0; i < M; i++)
{
int u, v;
scanf("%d%d", &u, &v);
bool hasu = (find(u, T) != NULL);
bool hasv = (find(v, T) != NULL);
if (hasu == false && hasv == false)
{
printf("ERROR: %d and %d are not found.\n", u, v);
continue;
}
if (hasu == false && hasv == true)
{
printf("ERROR: %d is not found.\n", u);
continue;
}
if (hasu == true && hasv == false)
{
printf("ERROR: %d is not found.\n", v);
continue;
}
if (u == v)
{
printf("%d is an ancestor of %d.\n", u, v);
continue;
}
int ans = getLCA(T, u, v);
if (ans == u)
{
printf("%d is an ancestor of %d.\n", u, v);
continue;
}
if (ans == v)
{
printf("%d is an ancestor of %d.\n", v, u);
continue;
}
printf("LCA of %d and %d is %d.\n", u, v, ans);
}
return 0;
}