十九、二叉树的最近的公共祖先
生活随笔
收集整理的這篇文章主要介紹了
十九、二叉树的最近的公共祖先
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
十九、二叉樹的最近的公共祖先
文章目錄
- 十九、二叉樹的最近的公共祖先
- 題目描述
- 解題思路
- 上機代碼:
題目描述
設順序存儲的二叉樹中有編號為 i 和 j 的兩個結點,請設計算法求出它們最近的公共祖先結點的編號和值。
輸入:
? 輸入第1行給出正整數n(≤1000),即順序存儲的最大容量;
第2行給出n個非負整數,其間以空格分隔。其中0代表二叉樹中的空結點(如果第1個結點為0,則代表一棵空樹);
第3行給出一對結點編號 i 和 j 。
題目保證輸入正確對應一棵二叉樹,且1≤ i,j ≤n。
輸出:
如果i或j對應的是空結點,則輸出:ERROR: T[x] is NULL,其中 x 是 i 或 j 中先發現錯誤的那個編號;否則在一行中輸出編號為 i 和 j 的兩個結點最近的公共祖先結點的編號和值,其間以一個空格分隔。
| 測試用例 1 | 15 4 3 5 1 10 0 7 0 2 0 9 0 0 6 8 11 4 | 2 3 | 1秒 | 64M | 0 |
| 測試用例 2 | 15 4 3 5 1 0 0 7 0 2 0 0 0 0 6 8 12 8 | ERROR: T[12] is NULL | 1秒 | 64M | 0 |
| 測試用例 3 | 15 4 3 5 1 0 0 7 0 2 0 0 0 0 6 8 8 12 | ERROR: T[8] is NULL | 1秒 | 64M | 0 |
解題思路
求解結點的最近公共祖先(Least Common Ancestors,LCA),做法如下:
從根節點開始遍歷
- 如果node1和node2中的任一個和root匹配,那么root就是最低公共祖先。
- 如果都不匹配,則分別遞歸左、右子樹,
- 如果有一個節點出現在左子樹,并且另一個節點出現在右子樹,則root就是最低公共祖先.
- 如果兩個節點都出現在左子樹,則說明最低公共祖先在左子樹中,否則在右子樹。
注意,如果 i、j 是空節點,直接輸出 ERROR。
上機代碼:
在二叉樹的存儲結構中,data是輸入序列中二叉樹結點的值,vis是按照完全二叉樹的順序對應二叉樹的結點的編號。通過 vis 可以更簡單地判斷二叉樹向下查找時有沒有超出邊界,同時通過打印 vis 可以知道二叉樹有沒有正確地建立。
下面代碼中的兩個函數 in_sequence()、print(),通過中序遍歷打印 data 和 vis 的值,我借此來判斷二叉樹有沒有正確建立,與本題關系不大。
#include<cstdio> #include<iostream> #include<queue> #include<cstring> #include<cstdlib> #include<algorithm> using namespace std; typedef struct NODE {int data; //結點的值int vis; //結點的序號struct NODE *lchild;struct NODE *rchild; }node, *Tree;queue<Tree>q; int n = 0, a[1010];//數組存儲結點信息void createTree() {int flag = 0;Tree T, N;T = (Tree)malloc(sizeof(node));cin >> n;for (int i = 1; i <= n; i++)cin >> a[i];//建立二叉樹while (!q.empty()){flag++;T = q.front();q.pop();T->data = a[flag];T->vis = flag;N = (Tree)malloc(sizeof(node));N->data = -1;N->vis = -1;//沒有訪問過T->lchild = N;q.push(N);N = (Tree)malloc(sizeof(node));N->data = -1;N->vis = -1;T->rchild = N;q.push(N);if (flag == n)break;} } void in_sequence(Tree T) {if (T->data != -1){in_sequence(T->lchild);cout << T->data << " ";in_sequence(T->rchild);}return; } void print(Tree T) {if (T->data != -1){print(T->lchild);cout << T->vis << " ";print(T->rchild);}return; } Tree LCA(Tree T,int u,int v) {if (T->vis == -1)//超出搜索范圍return T;if (T->vis == u || T->vis == v)//找到u,v的值return T;Tree cur = (Tree)malloc(sizeof(node));//遞歸左右子樹Tree left_lca = (Tree)malloc(sizeof(node));left_lca = LCA(T->lchild, u, v);if (left_lca->vis != -1){cur = LCA(left_lca->lchild, u, v);if (cur->vis != -1)cur = LCA(left_lca->rchild, u, v);if ((cur->vis == u && left_lca->vis == v) || (cur->vis == v && left_lca->vis == u))return T;}Tree right_lca = (Tree)malloc(sizeof(node));right_lca = LCA(T->rchild, u, v);if (right_lca->vis != -1){cur = LCA(right_lca->lchild, u, v);if (cur->vis != -1)cur = LCA(right_lca->rchild, u, v);if ((cur->vis == u && right_lca->vis == v) || (cur->vis == v && right_lca->vis == u))return T;}if (left_lca->vis != -1 && right_lca->vis != -1)return T;if (left_lca->vis == -1)return right_lca;elsereturn left_lca; } int main() {memset(a, -1, sizeof(a));Tree bit;bit = (Tree)malloc(sizeof(node));q.push(bit);createTree();/*in_sequence(bit);printf("\n");print(bit);printf("\n");*/int u = 0, v = 0;cin >> u >> v;if (a[u]==0){printf("ERROR: T[%d] is NULL\n", u);//system("pause");return 0;}else if (a[v]==0){printf("ERROR: T[%d] is NULL\n", v);//system("pause");return 0;}else{Tree tmp = (Tree)malloc(sizeof(node));tmp=LCA(bit, u, v);printf("%d %d\n", tmp->vis, tmp->data);}//system("pause");return 0; } 《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的十九、二叉树的最近的公共祖先的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 十八、二叉树遍历序列还原
- 下一篇: 二十、 二叉树的同构