1. 程式人生 > >二叉樹中找兩個結點的最近的公共祖先結點

二叉樹中找兩個結點的最近的公共祖先結點

#pragma once
#include <iostream>
using namespace std;

/****************
 * 二叉樹中 找兩個結點的最近的公共祖先結點
******************/

struct Node
{
    Node* left;
    Node* right;
    int value;

    Node(int v)
        :value(v)
        ,left(NULL)
        ,right(NULL)
    {}
};

// 方法一 int count 計數

int _find_ancestor(Node* root, Node* & ancestor, const Node* a, const Node* b)
{
    if (root == NULL)
    {
        return 0;
    }
    int count = 0;
  

    count += _find_ancestor(root->left, ancestor, a , b);

    if (root == a || root == b)
    {
        count += 1;
    }
    /*if (count == 2)
    {
        ancestor = root;
    }*/

   count += _find_ancestor(root->right, ancestor, a, b);

    if (count == 2)
    {
        ancestor = root ;
        count = 0; // 防止返回 時 上面count的值還是2 導致 ancestor不準確 被覆蓋
    }
    
    return count;

}

void test_find_ancestor()
{
   //     1
    //  2   3
    // 4  5
    Node n1(1);
    Node n2(2);
    Node n3(3);
    Node n4(4);
    Node n5(5);

    n1.left = &n2;
    n1.right = &n3;
    n2.left = &n4;
    n2.right = &n5;

    Node* ancestor = NULL;
    // 4 5
   // _find_ancestor(&n1, ancestor,&n4, &n5); 

    // 2 5
   // _find_ancestor(&n1, ancestor,&n2, &n5); 

    // 5 3
     _find_ancestor(&n1, ancestor,&n5, &n3); 
}

// 方法二 bool判別

bool find_ancestor_bool(Node* root, Node* & ancestor, const Node* a, const Node* b)
{
    if (root == NULL)
    {
        return false;
    }
  
    bool  b_left = find_ancestor_bool(root->left, ancestor, a, b);

    bool b_right = find_ancestor_bool(root->right, ancestor, a, b);
    
    
    if (root == a || root == b)
    {
        if (b_left || b_right)
        {
            ancestor = root;
        }

        return true;
    }

    if (b_left && b_right)
    {
        ancestor = root;
    }

    return b_left || b_right;

}


void test_find_ancestor_bool()
{
   //     1
    //  2   3
    // 4  5
    Node n1(1);
    Node n2(2);
    Node n3(3);
    Node n4(4);
    Node n5(5);

    n1.left = &n2;
    n1.right = &n3;
    n2.left = &n4;
    n2.right = &n5;

    Node* ancestor = NULL;
    // 4 5
    //find_ancestor_bool(&n1, ancestor,&n4, &n5); 

    // 2 5
   // find_ancestor_bool(&n1, ancestor,&n2, &n5); 

    // 5 3
    // find_ancestor_bool(&n1, ancestor,&n5, &n3); 
     // 1 5
     find_ancestor_bool(&n1, ancestor,&n1, &n5); 
}

// 方法3 利用棧 陣列或 連結串列 記錄 找到結點的 路徑  最後 遍歷兩個 棧(陣列或連結串列) 找到第一次出現比相同的點的前一個 即為公共祖先

// 注意 如果當前不是 返回時 要將當前壓棧的 元素彈出 棧用引用傳入

// 這裡以 vector 為例 方便遍歷

#include<vector>

void find_ancestor_vector_R(Node* root, vector<Node*>& va,vector<Node*>& vb, Node* a, Node* b, Node* &ancestor)
{
    if (root == NULL)
    {
        return;
    }

    va.push_back(root);
    vb.push_back(root);

    find_ancestor_vector_R(root->left, va, vb, a, b, ancestor);
    find_ancestor_vector_R(root->right, va, vb, a, b, ancestor);
    
    if (va.back() != a)
    {
        va.pop_back();    
    }

    if (vb.back() != b)
    {
        vb.pop_back();
    }
}

Node* find_ancestor_vector(Node* root, Node* a, Node* b)
{
    vector<Node*> va,vb;
    Node* ancestor = NULL;

    find_ancestor_vector_R(root, va, vb, a, b, ancestor);

    // 找va vb 的分叉點 之前的點 
    int i = 0;
    while (i < va.size() && i < vb.size() && va[i] == vb[i])
    {
        ancestor = va[i];
        i++;
    }

    return ancestor;
}

void  test_find_ancestor_vector()
{
    //     1
    //  2   3
    // 4  5
    Node n1(1);
    Node n2(2);
    Node n3(3);
    Node n4(4);
    Node n5(5);

    n1.left = &n2;
    n1.right = &n3;
    n2.left = &n4;
    n2.right = &n5;

    Node* ancestor = NULL;
    // 4 5
    ancestor = find_ancestor_vector(&n1, &n4, &n5); 

    // 2 5
    ancestor = find_ancestor_vector(&n1, &n2, &n5); 

    // 5 3
    ancestor = find_ancestor_vector(&n1, &n5, &n3); 
     // 1 5
     ancestor = find_ancestor_vector(&n1, &n1, &n5); 
}

相關推薦

【資料結構】任意節點的最近公共祖先節點

問題要求:任意給出二叉樹中的兩個節點,求他們的最近祖先 分三種情況: 1、該二叉樹是搜尋二叉樹 如果兩個節點的值都大於根節點,則遍歷右子樹查詢一個處於兩節點之間的值為最近祖先,如果兩個節點的值都小於根節點,則遍歷左子樹查詢一個兩節點之間的值為最近祖先 插入程式碼 Node*

結點最近公共祖先結點

一、搜尋二叉樹:第一變種是二叉樹是一種特殊的二叉樹:查詢二叉樹。也就是樹是排序過的,位於左子樹上的結點都比父結點小,而位於右子樹的結點都比父結點大。我們只需要從根結點開始和兩個結點進行比較。如果當前結點的值比兩個結點都大,則最低的共同父結點一定在當前結點的左子樹中。如果當前

結點最近公共祖先結點

#pragma once #include <iostream> using namespace std; /****************  * 二叉樹中 找兩個結點的最近的公共祖先結

演算法:在尋找節點的共同祖先

問題:已知二叉樹root和兩個節點p和q,要求找出p和q在root中的最早的共同祖先。要求:該二叉樹的節點沒有parent指標(如果有parent指標,演算法會簡單很多)。 演算法思想:中序訪問二叉樹,對於當前節點,當其左子樹和右子樹訪問完畢,且p與q都已經訪問過,則當前節

結點的第一公共祖先

題目分析:假設1:這個二叉樹是二叉排序樹(O(N)) 如果題目中的二叉樹是二叉排序樹,那麼這道題目變的相對簡單很多,我們只需要從根節點開始遍歷,有以下三種情況發生: (1)如果題目給的兩個節點的值都大於當前節點,那麼繼續遍歷當前節點的右子樹 (2)如果題目給的兩個節點的值都小於當前節點,那麼繼續遍歷當前節點的

任意結點的距離

case itl wid get ren return roo [] fall 求二叉樹中任意兩個結點的距離實現步驟:計算跟到第一個結點的距離;計算跟到第二個結點的距離;計算lca;計算跟到lca結點的距離;結果為(1) + (2) - 2 * (4),因為重復計算了兩次的

任意結點間的路徑(C++)

方法一 #include <iostream> #include <vector> using namespace std; struct Node { int val; Node* left; Node* right; Node(int v

任意節點的最近公共祖先

stc node comm cnblogs blog style == spa 發現 public class Solution { public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p,

3.18 在找到節點的最近公共祖先

【題目】:   給定一棵二叉樹的頭節點head,以及這棵樹中的兩個節點o1和o2,請返回o1和o2的最近公共祖先節點   例如,如下圖所示的二叉樹:                       1                       2    

系列---在找到節點的最近公共祖先

題目 給定一顆二叉樹的頭結點,和這顆二叉樹中2個節點n1和n2,求這兩個節點的最近公共祖先; 思路 利用後序遍歷實現; 對於當前節點cur,如果節點為null或者等於n1或n2中的一個,則直接返回cur; 先處理左右子樹,左子樹返回left,右子樹

【劍指offer{4-6}】重建、用棧實現佇列、旋轉陣列的最小數字

重建二叉樹、用兩個棧實現佇列、旋轉陣列的最小數字重建二叉樹題目描述C++程式碼題目描述C++程式碼題目描述C++程式碼 重建二叉樹 題目描述 輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹

LeetCode(Binary Tree Maximum Path Sum) 在出一條和最大的路徑

題目要求: Given a binary tree, find the maximum path sum. The path may start and end at any node in the tree. For example: Given the belo

求出出和為某一值的所有路徑

前段時間什麼也不懂,就跑到騰訊去面試,然後面試官出了這道題,當時已碰演算法就悶,現在給出這道題目的解 另外再次感謝July仁兄對於各種面試題的整理,讓我有這些經典的題來練習。 題目:輸入一個整數和一棵二元樹。 從樹的根結點開始往下訪問一直到葉結點所經過的所有結點形成一條路徑

出和為某一值的所有路徑-java實現

一個小演算法,分享一下思路: 描述: 寫一個程式建立一棵二叉樹,並按照一定規則,輸出二叉樹根節點到葉子節點的路徑。 規則如下: 1、從最頂端的根結點,到最下面的葉子節點,計算路徑通過的所有節點的和,如果與設定的某一值的相同,那麼輸出這條路徑上的所有節點。 2、從根節點遍歷

任意節點的最低共同父節點

通過兩個和二叉樹相關的演算法題來看看和遞迴在二叉樹中的應用 輸入二叉樹中的兩個結點,輸出這兩個結點在數中最低的共同父結點。 思路: 如果這兩個節點不在同一個子樹下面,那麼這棵樹的根節點就是他們的共同最低父節點。 如果兩個都在右子樹,那麼以右子樹的最上面的那個節點作為根節點

搜尋的最小節點絕對值之差/在查詢尋找節點,使它們的和為一個給定值/出 BST 的所有眾數(出現頻率最高的元素)。

關於二叉樹的數值運算,一般考慮借用中序遍歷為陣列;再進行計算的思想。 /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; *

節點的最近公共祖先結點

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

查詢尋找節點,使它們的和為一個給定值

給定一個二叉搜尋樹和一個目標結果,如果 BST 中存在兩個元素且它們的和等於給定的目標結果,則返回 true。 使用中序遍歷得到有序陣列之後,再利用雙指標對陣列進行查詢。 應該注意到,這一題不能用分別在左右子樹兩部分來處理這種思想,因為兩個待求的節點可能分別在左右子樹中。 /** *

3.10 調整搜尋錯誤的節點

【題目】:   一棵二叉樹原本是搜尋二叉樹,但是其中有兩個節點調換了位置,使得這棵二叉樹不再是搜尋二叉樹,請找到這兩個錯誤節點並返回。已知二叉樹中所有節點的值都不一樣,給定二叉樹的頭節點head,返回一個長度為2的二叉樹節點型別的陣列errs,errs[0]表示一個錯誤節點,errs[1]表示另一個錯誤節點

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

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