题目
- 原文:
Design an algorithm and write code to find the first common ancestor of two nodes in a binary tree. Avoid storing additional nodes in a data structure. NOTE: This is not necessarily a binary search tree. - 译文:
写程序在一棵二叉树中找到两个结点的第一个共同祖先。不允许存储额外的结点。注意: 这里不特指二叉查找树。
分析
这里提到不允许存储额外的结点,那么我们就不能通过先找到两个结点的所有父节点储存起来,再一一比对的方法,这里用哈希比map快。
TreeNode* first_ancestor(TreeNode* n1, TreeNode* n2){
if(n1 == NULL || n2== NULL) return NULL;
map<TreeNode*, bool> m;
while(n1){
m[n1] = true;
n1 = n1->parent;
}
while(n2 && !m[n2]){
n2 = n2->parent;
}
return n2;
}
取而代之的,如果不使用额外空间,并且没有父节点指针,我们从根节点开始依次向下找两节点共同祖先结点,直到找到最后一个这两结点的共同祖先结点。
这里值得注意的是:
关于指针的引用:
在主函数中定义了一个指针,要将这个指针做参数传给子函数,在子函数中开辟两兆内存,这个时候一定要用指针的引用。
因为指针所指的这块内存发生了改变,或者说指针的指向发生了改变。
主函数中只是定义了一个指针,并没有真正开辟内存,子函数中才真正开辟内存,指针指向哪才明确下来。
如果你有时候不清楚该不该用变量的引用做参数,那就记住一点: 用指针的引用总是没有问题的。因为传递变量的地址比传递变量本身总是改的快。
学习来源:https://blog.csdn.net/matrix_google/article/details/77543192
代码
#include<iostream>
using namespace std;
struct TreeNode {
int val;
TreeNode *leftchild, *rightchild;
};
TreeNode* createNode(int val) {
TreeNode* node = new TreeNode;
node->leftchild = NULL;
node->rightchild = NULL;
node->val = val;
return node;
}
//void insert(TreeNode **tree, int val) {
// if(*tree == NULL) {
// *tree = createNode(val);
// return;
// }
// else if((*tree)->val >= val) {
// return insert(&(*tree)->leftchild, val);
// }
// else {
// return insert(&(*tree)->rightchild, val);
// }
//}
void insert(TreeNode* &tree, int val) {
if(tree == NULL) {
tree = createNode(val);
return;
}
else if(tree->val >= val) {
return insert(tree->leftchild, val);
}
else {
return insert(tree->rightchild, val);
}
}
TreeNode* findNode(TreeNode* head, int val) {
if(head == NULL) {
return NULL;
}
else if(head->val == val) {
return head;
}
else if(head->val >= val) {
return findNode(head->leftchild, val);
}
else {
return findNode(head->rightchild, val);
}
}
bool father(TreeNode* n1, TreeNode* n2) {
if(n1 == NULL) {
return false;
}
else if(n1 == n2) {
return true;
}
else {
return father(n1->leftchild, n2) || father(n1->rightchild, n2);
}
}
void first_ancestor(TreeNode* head, TreeNode* n1, TreeNode* n2, TreeNode* &ancnode) {
if(head == NULL || n1 == NULL || n2 == NULL) {
return;
}
if(head && father(head, n1) && father(head, n2)) {
ancnode = head;
first_ancestor(head->leftchild, n1, n2, ancnode);
first_ancestor(head->rightchild, n1, n2, ancnode);
}
return;
}
void printTree(TreeNode *tree) {
if(tree != NULL) {
cout << tree->val << " ";
printTree(tree->leftchild);
printTree(tree->rightchild);
}
}
void deleteTree(TreeNode *tree) {
if(tree != NULL) {
deleteTree(tree->leftchild);
deleteTree(tree->rightchild);
delete tree;
}
}
int main() {
TreeNode *tree = NULL;
int a[] = {
5, 3, 8, 1, 4, 7, 10, 2, 6, 9, 11, 12
};
for(int i=0; i<12; ++i)
insert(tree, a[i]);
cout << "the tree is: ";
printTree(tree);
cout << endl;
TreeNode* n1 = findNode(tree, 1);
TreeNode* n2 = findNode(tree, 2);
TreeNode* ancnode = NULL;
first_ancestor(tree, n1, n2, ancnode);
cout << n1->val << " and " << n2->val << "'s father is" << ancnode->val << endl;
deleteTree(tree);
}
结果展示