1. 程式人生 > >求二叉樹中兩個節點的最近公共祖先(三叉鏈,搜尋樹,普通二叉樹)

求二叉樹中兩個節點的最近公共祖先(三叉鏈,搜尋樹,普通二叉樹)

求二叉樹中兩個節點的最近公共祖先。

要求:分別考慮以下三種情況
       1、二叉樹每個節點有parent(三叉鏈)
       2、二叉樹是搜尋二叉樹。
       3、就是普通二叉樹。(儘可能實現時間複雜度為O(N))

這裡寫圖片描述

節點:
struct Node
{
    int _data;
    Node* _left;
    Node* _right;
    Node* _parent;

    Node(int x)
        :_data(x)
        , _left(NULL)
        , _right(NULL)
        , _parent(NULL
) {} };

一、二叉樹每個節點有parent(三叉鏈)

       這裡介紹兩種方法並提供程式碼實現。
第一種方法:
       Node* CommonAncester0(Node* node1, Node* node2)
       把從node1和node2到根節點分別看做兩個單鏈表,定義一個指標tmp遊走node2這條連結串列,node1每走一個節點將node2遍歷一遍,同時將tmp->_parent對比,若相等,node1即為公共祖先節點;不相等繼續遊走。
       程式碼如下:

Node* CommonAncester0(Node* node1, Node*
node2) { if (node1 == NULL || node2 == NULL) return NULL; Node* tmp = node2; while (node1) { node1 = node1->_parent; tmp = node2; while (tmp) { if (node1 == tmp->_parent) return node1; tmp = tmp->
_parent; } } return NULL; }

第二種方法:
       把從node1和node2到根節點分別看做兩個單鏈表,看做尋找兩個相交單鏈表的交點問題來解決。
這裡寫圖片描述
       程式碼:

Node* CommonAncester1(Node* node1, Node* node2)
{
    if (node1 == NULL || node2 == NULL)
        return NULL;
    //先計算連結串列長度
    int len1 = Length(node1);
    int len2 = Length(node2);
    int sub = 0;
    Node* fast = NULL;
    Node* slow = NULL;

    if (len1 >= len2)
    {
        sub = len1 - len2;
        fast = node1;
        slow = node2;
        while (sub--)
            fast = fast->_parent;
        while (fast)
        {
            if (fast == slow)
                return fast;
            fast = fast->_parent;
            slow = slow->_parent;
        }
    }
    else
    {
        sub = len2 - len1;
        fast = node2;
        slow = node1;
        while (sub--)
            fast = fast->_parent;
        while (fast)
        {
            if (fast == slow)
                return fast;
            fast = fast->_parent;
            slow = slow->_parent;
        }
    }
    return NULL;
}

二、二叉樹是搜尋二叉樹

搜尋二叉樹特點:
       任意一個節點的左子樹的值都小於該節點的值,右子樹的值都大於該節點的值。
       從二叉樹的根節點開始比較,若兩個節點的值都比根節點值大,則公共祖先節點一定在右子樹,繼續在右子樹中用相同方法查詢;若都比根節點值小,則公共祖先節點一定在左子樹,繼續在左子樹中查詢;若兩個節點的值一個大於根節點的值,一個小於根節點的值,則公共祖先節點為根節點。
       程式碼:

Node* CommonAncester2(Node* root, Node* node1, Node* node2)
{
    if (root == NULL || node1 == NULL || node2 == NULL)
        return NULL;
    if ((root->_data > node1->_data && root->_data < node2->_data) || (root->_data > node2->_data && root->_data < node1->_data))
        return root;
    else if (root->_data < node1->_data && root->_data < node2->_data)
        return CommonAncester2(root->_right, node1, node2);
    else if (root->_data == node1->_data || root->_data == node2->_data)
        return root;
    else
        return CommonAncester2(root->_left, node1, node2);
}

三、普通二叉樹

方法1:
       分別找到node1和node2到根節點的路徑儲存在兩個vector中,然後遍歷兩個vector,直到找到不同的節點。
這裡寫圖片描述
方法2:
       先從根節點開始遍歷,若node1或node2中一個與root相同,則根節點即為公共節點;遞迴查詢節點 ,若一個節點在root左子樹,一個節點在root右子樹,root為公共祖先;如果兩個節點都出現在左子樹,則說明最低公共祖先在左子樹中,否則在右子樹。

Node* CommonAncester3(Node* root, Node* node1, Node* node2)
{
    if (root == NULL || node1 == NULL || node2 == NULL)
        return NULL;
    if (node1 == root || node2 == root)
        return root;

    Node* cur = NULL;
    Node* left = CommonAncester3(root->_left, node1, node2);
    if (left)
    {
        cur = CommonAncester3(left->_left, node1, node2);
        if (cur == NULL)
            cur = CommonAncester3(left->_right, node1, node2);
        if ((cur == node1&&left == node2) || (cur == node2&&left == node1))
            return root;
    }

    Node* right = CommonAncester3(root->_right, node1, node2);
    if (right)
    {
        cur = CommonAncester3(right->_left, node1, node2);
        if (cur == NULL)
            cur = CommonAncester3(right->_right, node1, node2);
        if ((cur == node1&&right == node2) || (cur == node2&&right == node1))
            return root;
    }

    if (left&&right)
        return root;
    if (left == NULL)
        return right;
    else
        return left;
}

相關推薦

節點最近公共祖先三叉搜尋普通

求二叉樹中兩個節點的最近公共祖先。 要求:分別考慮以下三種情況        1、二叉樹每個節點有parent(三叉鏈)        2、二叉樹是搜尋二叉樹。        3、就是普通二

結點的最低公共祖先C++實現

題目是,輸入兩個樹結點,求它們的最低公共祖先 首先,要說明的是,這是一組題目,根據劍指Offer上所講的,這道題可能會分好幾種情況,因此,如果在面試時候遇到,我們需要和麵試官溝通,而不是一上來就寫程式碼。 1. 如果給定樹是二叉搜尋樹 二叉

節點最近公共祖先結點

二叉樹是搜尋二叉樹 1、原理:二叉搜尋樹是排序過的 ,位於左子樹的結點都比父結點小,位於右子樹的結點都比父結點大,我們只需從根節點開始和兩個輸入的結點進行比較,如果當前節點的值比兩個結點的值都大,那麼最低的公共祖先結點一定在該結點的左子樹中,下一步開遍歷當前結點的左子樹。如

節點最近公共祖先節點

#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<vector> using std::cin; using std::cout; usi

ODOA(2) 節點的最大距離(C語言實現)

問題描述; 如果我們把二叉樹看成一個圖,父子節點之間的連線看成是雙向的,我們姑且定義"距離"為兩節點之間邊的個數。寫一個程式求一棵二叉樹中相距最遠的兩個節點之間的距離。 演算法很容易想得到: 如果根節點的左子樹或右子樹為空,那麼最大距離即為樹的深度否則,最大距離等於

節點最遠的距離

一說到二叉樹,就有很多題目,今天在程式設計之美中看到了二叉樹中兩個節點最遠的距離。所以給想借機寫一篇部落格。 在開始之前,我們先想想,兩個最常節點的最遠距離是怎麼樣的? 情況一:最大距離可能一個在左子

節點的最小公共祖先LCA

題目要求:求二叉樹中兩個節點p,q的最低公共祖先節點 首先,題目中沒有明確說明節點的結構,所以思考了一會然後問面試官節點有沒有父指標,面試官說有沒有父指標有影響嗎?我說有,然後他笑著說你來說說看。當時,只做出來有父指標的情況,沒有父指標的情況壓根想不出來。後

程式設計師面試100題之十六 節點最近公共節點

                這個問題可以分為三種情況來考慮:情況一:root未知,但是每個節點都有parent指標此時可以分別從兩個節點開始,沿著parent指標走向根節點,得到兩個連結串列,然後求兩個連結串列的第一個公共節點,這個方法很簡單,不需要詳細解釋的。情況二:節點只有左、右指標,沒有parent

《程式設計師面試金典》--尋找節點的第一公共祖先三種情況

/**************************************************************************************************

搜尋節點最近公共祖先

搜尋二叉樹中兩個節點的最近公共祖先 Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in the BST. According to the

資料結構演算法題/節點最近公共節點

這個問題可以分為三種情況來考慮: 情況一:root未知,但是每個節點都有parent指標 此時可以分別從兩個節點開始,沿著parent指標走向根節點,得到兩個連結串列,然後求兩個連結串列的第一個公共節點,這個方法很簡單,不需要詳細解釋的。 情況二:節點只有左、右指標,沒有parent指標,roo

節點的最低公共節點

問題描述 構建一棵二叉樹(不一定是二叉查詢樹),求出該二叉樹中某兩個結點的最低公共父結點。借用一張圖如下: 最低公共父結點的思路 遞迴,首先從樹根開始考慮: ①結點A 和 結點B 要麼都在樹根的左子樹中;②要麼都在樹根的右子樹中;③要麼一個在左子樹中

節點最近公共祖先leetcode

leetcode題目地址 二叉樹構造 TreeNode* t1 = new TreeNode(3); TreeNode* t2 = new TreeNode(5); TreeNode* t3 = new TreeNode(1);

問題——尋找節點最近公共祖先

此題大概分為3種情況: 1、節點中無parent,但提供了root (1)、此種情況又分為兩種,開闢空間,使用容器來儲存路徑,將其轉換為求連結串列公共節點的問題,時間複雜度為O(N),空間複雜度為O(N) (2)、不開闢空間,在節點的左右子樹上尋找兩個節點

節點最近公共節點

轉載:http://blog.csdn.net/hackbuteer1/article/details/8022138# 這個問題可以分為四種情況來考慮:情況一:root未知,但是每個節點都有parent指標此時可以分別從兩個節點開始,沿著parent指標走向根節點,得到兩

應用_節點的最低公共祖先

題目:給定樹中的兩個節點,找出這兩個節點的最低公共祖先。 情況1:當給定的樹為二叉搜尋樹時。 分析:由於二叉搜尋樹是排序過的,位於左子樹的節點都小於根節點,位於右子樹的節點都大於根節點。如果要查詢的兩個節點比根節點大的話,則最低公共祖先在右子樹中;如果要查詢

節點最近公共祖先節點方法全集

一.如果資料結構為三叉連結串列,即含有指向父節點的指標: Node * NearestCommonAncestor(Node * root,Node * p,Node * q) { Node *

尋找節點最近公共祖先——迅雷筆試歸來

      迅雷的筆試可真讓人煎熬啊,題量很大,而且考試時間是三個小時。不過迅雷的題目質量很高,既考查了基礎知識又不乏高難的資料結構和演算法題目。下面和大家分享兩道演算法程式設計題,程式碼沒有在編譯器上除錯,可能會出現一點小bug,感興趣的朋友可以編譯除錯一下。 題目1:將

節點的最低公共祖先節點go

該題目有以下幾種情況可以考慮 1. 樹是二叉搜尋樹,二叉搜尋樹的特點是根節點值大於所有左子樹節點值,小於所有右子樹節點值,則最低公共祖先即該節點值大於給定兩個節點中的一個值,小於另外一個節點的值,go程式碼實現如下 type TreeNode struct { Val int Lef

以及搜尋節點公共祖先

題目如標題,解法都可以按照如下: /** * Definition for a binary tree node. * struct TreeNode { * int val;