1.树节点定义中带有parent指针
struct TreeNode { int data; TreeNode *left,*right,*parent; };
(1). p->parent
(2). 将q的所有祖先节点依次和p->parent作比较,如果发现两个节点相等,则该节点就是最近公共祖先,直接将其返回。如果没找到相等节点,则转3
(3).p = p->parent,转2
主要代码如下:
const TreeNode* FindNCA(const TreeNode* root,const TreeNode* p,const TreeNode* q) { if(root==NULL || p==NULL || q==NULL) return NULL; while(p) { p = p->parent; const TreeNode* tmp = q; while(tmp) { if(p == tmp->parent) return p; tmp = tmp->parent; } } } void TestNCA() { TreeNode *root = newTreeNode(2); TreeNode *p1 = newTreeNode(1); root->left = p1; p1->parent = root; TreeNode *p4 = newTreeNode(4); root->right = p4; p4->parent = root; TreeNode *p3 = newTreeNode(3); root->right->left = p3; p3->parent = root->right; TreeNode *p5 = newTreeNode(5); root->right->right = p5; p5->parent = root->right; // Constructed binary search tree is // 2 // / \ // 1 4 // / \ // 3 5 const TreeNode* out = FindNCA(root,p1,p5); if(out) printf("\nResult pointer is %d", out->data); else printf("\nNot find pointer"); }
另外一种可能会降低时间复杂度的方法:
算法思想:
(1). 从root到p建立一条链表list1,从root到q建立一条链表list2
(2). 问题转为为求list1和list2的最后一个相同的节点
主要代码如下
struct Node //链表节点 { Node* next; int data; };
bool PushFront(Node** phead, int data) { Node* newNode = new Node; if(newNode == NULL) return false; newNode->data = data; newNode->next = *phead;//无论*phead是否为空都行 *phead = newNode; return true; }
const Node* FindLastSameNode(const Node* head1,const Node* head2) { if(head1==NULL || head2==NULL) return NULL; const Node* prev1 = NULL; //本来应该写成head1==head2,但是这里的实现不大好 while(head1 && head2 && head1->data==head2->data) { prev1 = head1; head1 = head1->next; head2 = head2->next; } return prev1; }
const Node* FindNCA(const TreeNode* root,const TreeNode* p,const TreeNode* q) { if(root==NULL || p==NULL || q==NULL) return NULL; Node *list1=NULL, *list2=NULL; while(p != NULL) { PushFront(&list1,p->data); p = p->parent; } //cout<<endl; while(q != NULL) { PushFront(&list2,q->data); q = q->parent; } //cout<<"\nlist1: ";Print(list1); //for debug //cout<<"\nlist2: ";Print(list2); //for debug return FindLastSameNode(list1, list2); }
void TestNCA() { TreeNode *root = newTreeNode(2); TreeNode *p1 = newTreeNode(1); root->left = p1; p1->parent = root; TreeNode *p4 = newTreeNode(4); root->right = p4; p4->parent = root; TreeNode *p3 = newTreeNode(3); root->right->left = p3; p3->parent = root->right; TreeNode *p5 = newTreeNode(5); root->right->right = p5; p5->parent = root->right; // Constructed binary search tree is // 2 // / \ // 1 4 // / \ // 3 5 const Node* out = FindNCA(root,p1,p5); if(out) printf("\nResult pointer is %d", out->data); else printf("\nNot find pointer"); }
2.树节点定义中不带有parent指针
主要思想:节点cur的左子树包含一个节点(p或者q),右子树包含另一个节点(p或者q),则cur就是我们要找的节点。
//不带parent指针的树节点 struct TreeNode { int data; TreeNode *left,*right; };
TreeNode* newTreeNode(int data) { TreeNode* node = new TreeNode; node->data = data; node->left = NULL; node->right = NULL; return node; }
//返回root为根的树种包含p,q两个节点中节点的数目:0,1,2 int FindNCA(TreeNode* root,const TreeNode* p,const TreeNode* q,TreeNode** out) { if(root==NULL) return 0; if(root==p || root==q) return 1; int iLeft = FindNCA(root->left,p,q,out); if(iLeft==2) return 2; int iRight = FindNCA(root->right,p,q,out); if(iRight==2) return 2; if(iLeft+iRight==2) *out = root; return iLeft+iRight; }
void TestNCA() { TreeNode *root = newTreeNode(2); TreeNode *p1 = newTreeNode(3); root->left = p1; TreeNode *p4 = newTreeNode(3); root->right = p4; TreeNode *p3 = newTreeNode(3); root->right->left = p3; TreeNode *p5 = newTreeNode(5); root->right->right = p5; // Constructed binary search tree is // 2 // / \ // 1 4 // / \ // 3 5 TreeNode* out = NULL; int i = FindNCA(root, p1, p5, &out); if( i == 2 ) printf("Result pointer is %d", out->data); else printf("Not find pointer"); }