【劍指offer】近期公用祖先

來源:互聯網
上載者:User

標籤:des   style   blog   http   color   strong   

轉載請註明出處:http://blog.csdn.net/ns_code/article/details/28113959

    劍指offer上的最後一題了,一個遞迴函式調了一下午,才得到正確的結果。

題目描寫敘述:

給定一棵樹,同一時候給出樹中的兩個結點,求它們的最低公用祖先。

輸入:

輸入可能包括多個測試例子。
對於每一個測試案例,輸入的第一行為一個數n(0<n<1000),代表測試例子的個數。
當中每一個測試例子包括兩行,第一行為一個二叉樹的先序遍曆序列,當中左右子樹若為空白則用0取代,當中二叉樹的結點個數node_num<10000。
第二行為樹中的兩個結點的值m1與m2(0<m1,m2<10000)。

輸出:

相應每一個測試案例,
輸出給定的樹中兩個結點的最低公用祖先結點的值,若兩個給定結點無最低公用祖先,則輸出“My God”。

例子輸入:
21 2 4 6 0 0 7 0 0 5 8 0 0 9 0 0 3 0 06 81 2 4 6 0 0 7 0 0 5 8 0 0 9 0 0 3 0 06 12
例子輸出:
2My God
    這類的題目,方法蠻多的,思路也不難理解,基本都是各種遍曆的變種,主要是寫代碼,尤其基於遞迴的代碼。

    首先假設是二叉排序樹自然不用說了,推斷的一句就是該節點的值是否位於輸入的這兩個節點之間,能夠用前序走訪來做。

    假設是普通的樹或者二叉樹,解題思路是一樣的,能夠考慮前序走訪,得到兩個路徑,用鏈表或數組儲存起來,然後找出兩條路徑的最後一個公用節點就可以。也能夠後序遍曆的方式,遍曆到輸入的節點時,將該節點及其後面遍曆到的節點都儲存到一個鏈表或數組中,然後找出兩條路徑的第一個公用機節點就可以。

    以下採用的是前序走訪,並用數組儲存路徑的代碼。

#include<stdio.h>#include<stdlib.h>#include<stdbool.h>typedef struct BTNode{struct BTNode *lchild;struct BTNode *rchild;int data;}BTNode,*BTree;/*前序走訪找出根節點到資料域為val的節點路徑,儲存在path數組中,這裡index是儲存到path數組中的元素的下標,*len用來儲存路徑長度,假設能找到val,則返回ture,找不到則返回false*/bool GetPreTraversePath(BTree pTree,int val,int *path,int index,int *len){if(pTree == NULL){*len = 0;return false;}path[index] = pTree->data;if(pTree->data == val){*len = index+1;return true;}else{bool can;can = GetPreTraversePath(pTree->lchild,val,path,index+1,len);if(!can)can = GetPreTraversePath(pTree->rchild,val,path,index+1,len);return can;}}/*擷取兩個路徑的最後一個公用節點,因為對樹的先序遍曆的結果中,前面一定有些節點同樣,因此一定能找到最後一個同樣節點*/int GetFirstCommonNode(int *path1,int len1,int *path2,int len2){int shortLen = len1<len2 ? len1:len2;int i;for(i=0;i<shortLen;i++){if(path1[i] != path2[i])break;}return path1[i-1];}/*依據先序遍曆序列建立二叉樹,因為可能改變根節點的指向,因此傳入BTNode的二級指標*/void CreateBTree(BTree *pRoot){int data;scanf("%d",&data);if(data == 0)*pRoot = NULL;else{*pRoot = (BTree)malloc(sizeof(BTNode));if(*pRoot == NULL)exit(EXIT_FAILURE); (*pRoot)->data = data;(*pRoot)->lchild = NULL;(*pRoot)->rchild = NULL;CreateBTree(&((*pRoot)->lchild));CreateBTree(&((*pRoot)->rchild));}}/*銷毀二叉樹*/void DestroyBTree(BTree pRoot){if(pRoot != NULL){if(pRoot->lchild != NULL)DestroyBTree(pRoot->lchild);if(pRoot->rchild != NULL)DestroyBTree(pRoot->rchild);free(pRoot);pRoot = NULL;}}int main(){int path1[10000];int path2[10000];int n;while(scanf("%d",&n) != EOF){int i;for(i=0;i<n;i++){BTree pRoot = NULL;CreateBTree(&pRoot);int val1,val2;scanf("%d %d",&val1,&val2);int len1,len2;bool can1 = GetPreTraversePath(pRoot,val1,path1,0,&len1);bool can2 = GetPreTraversePath(pRoot,val2,path2,0,&len2);if(can1 && can2)printf("%d\n",GetFirstCommonNode(path1,len1,path2,len2));elseprintf("My God\n");DestroyBTree(pRoot);}}return 0;}
/**************************************************************      Problem: 1509      User: mmc_maodun      Language: C      Result: Accepted      Time:130 ms      Memory:920 kb ****************************************************************/    PS:尋找路徑的遞迴代碼調了一個下午,總算搞定了,每次碰到關於樹的問題,一般都是三種遍曆方式的變種來實現,自然想到遞推,有些寫著非常easy,有些寫著總非常糾結,尤其要返回bool變數的時候,還是太菜,回頭要抽個時間把二叉樹的遞迴實現的一些題目好好總結下。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.