1. 程式人生 > >二叉樹中兩個節點的最近公共祖先(leetcode)

二叉樹中兩個節點的最近公共祖先(leetcode)

leetcode題目地址

二叉樹構造

TreeNode* t1 = new TreeNode(3);
    TreeNode* t2 = new TreeNode(5);
    TreeNode* t3 = new TreeNode(1);

    TreeNode* t4 = new TreeNode(6);
    TreeNode* t5 = new TreeNode(2);

    TreeNode* t6 = new TreeNode(0);
    TreeNode* t7 = new TreeNode(8);

    TreeNode* t8 = new TreeNode(7
); TreeNode* t9 = new TreeNode(4); t1->left = t2; t1->right = t3; t2->left = t4; t2->right = t5; t3->left = t6; t3->right = t7; t5->left = t8; t5->right = t9; TreeNode* root = t1; /* _______3______ / \ ___5__ ___1__ / \ / \ 6 _2 0 8 / \ 7 4 */

AC1

使用dfs得到根結點到某個結點的路徑,然後比對路徑就可以得到最近的公共祖先

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:

    vector<TreeNode*> fa1;
    vector
<TreeNode*>
fa2; void dfs(vector<TreeNode*> &fa, TreeNode* root, TreeNode* p, TreeNode* q) { if (root == NULL) return ; if (root == p){ fa1 = fa; } if (root == q){ fa2 = fa; } if (root->left != NULL){ fa.push_back(root->left); dfs(fa,root->left, p,q); fa.pop_back(); } if (root->right != NULL) { fa.push_back(root->right); dfs(fa, root->right, p,q); fa.pop_back(); } } TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { vector<TreeNode*> fa; fa.push_back(root); dfs(fa, root, p,q); vector<TreeNode*>::iterator it1 = fa1.begin(); vector<TreeNode*>::iterator it2 = fa2.begin(); TreeNode* ans = NULL;; while (it1 != fa1.end() && it2 != fa2.end()) { if (*it1 == *it2) { ans = *it1; it1++; it2++; } else{ break; } } return ans; } };

ac2

遍歷二叉樹時,只有先訪問給定兩節點A、B後,才可能確定其最近共同父節點C,因而採用後序遍歷。

可以統計任一節點的左右子樹“是否包含A、B中的某一個”(也可以直接統計“包含了幾個A、B”)。當後序遍歷訪問到某個節點D時,可得到三條資訊:(1)節點D是否是A、B兩節點之一(2)其左子樹是否包含A、B兩節點之一(3)其右子樹是否包含A、B兩節點之一。當三條資訊中有兩個為真時,就可以確定節點D的父節點(或節點D,如果允許一個節點是自身的父節點的話)就是節點A、B的最近共同父節點。另外,找到最近共同父節點C後應停止遍歷其它節點。

原文的程式碼似乎不符合,我重新改寫了一下程式碼,ac如下:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:

    bool lca(TreeNode *root, TreeNode* va, TreeNode* vb, TreeNode *&result)  
    {  
        // left/right 左/右子樹是否含有要判斷的兩節點之一   
        bool left = false, right = false; 
        if (!result && root->left != NULL) 
            left = lca(root->left,va,vb,result);  
        if (!result && root->right != NULL) 
            right = lca(root->right,va,vb,result);  

        // mid 當前節點是否是要判斷的兩節點之一   
        bool mid = false;  
        if (root == va || root == vb) 
            mid = true;

        if (!result && int(left + right + mid) == 2) 
        {  
            result = root;// root就是後序遍歷(左,右,根),當前遍歷的那個節點
        }  
        return left | mid | right ;  
    }  

    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q)
    {
        if (root == NULL) 
            return NULL;

        TreeNode *result = NULL;
        lca(root, p, q,result);  

        return result;  
    }
};

相關推薦

程式設計師面試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

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

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

節點最近公共祖先leetcode

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

節點最近公共祖先結點

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

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

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

節點最近公共祖先節點

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

節點最近公共節點

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

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

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

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

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

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

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

節點的最低公共節點

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

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

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

節點最遠的距離

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

節點的最小公共祖先LCA

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

3.10 調整搜尋錯誤的節點

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

滿排序任意三節點最低公共節點

#include <iostream> using namespace std; int tree[1024*1024]; int k; int a,b,c; int power2(int n) { int i=1; int j; fo

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

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

——查詢任意節點最近祖先

很久沒有用過二叉樹了,最近由於需要用到了,發現很多知識需要鞏固了,中間涉及到一個演算法就是找任意兩個節點的最近祖先。通過本人回顧和演算,最終提出了下面一個方法,網上也有很多其他的方式實現,再次僅對自己好幾個小時的工作作個記錄和積累吧! 程式是用C語言寫的,個人覺得如果用C#