求二叉樹的給定兩個結點之間的距離

OpenSoucre發表於2014-07-02

給定一顆二叉樹,和兩個給定的結點,求出這兩個結點之間的距離

拿到題目時不要認為是求出二叉樹的結點之間的最大距離,題目是求兩個結點的之間的距離

題目有幾種情況

  • 兩個結點分佈在根節點的左子樹或者右子樹
  • 一個結點分佈在根節點的左子樹,一個結點分佈在根節點的右子樹
  • 這兩個結點是兄弟結點
  • 一個結點是另外結點的祖先結點

本題的解題思路是

利用層次遍歷的方法,獲取每個結點的高度,根節點左子樹的高度用正數表示,根節點右子樹的高度用負數表示

這樣當兩個結點分佈在:一個結點分佈在根節點的左子樹,一個結點分佈在根節點的右子樹時,只需要兩個結點的高度的差得絕對值即可

如果一個結點是另一個結點的祖先結點,只需要高度大的結點順著祖先結點找到高度小得結點,如果到達相同的高度結點不相同說明是兄弟結點關係

#include <iostream>
#include <vector>
#include <queue>
#include <stack>
#include <string>
#include <algorithm>

using namespace std;

struct TreeNode{
    int val;
    TreeNode* left;
    TreeNode* right;
    TreeNode(int val_ = 0):val(val_),left(NULL),right(NULL){}
};

struct TreeHeightNode{
    int height;
    TreeNode* node;
    TreeHeightNode* parent;
    TreeHeightNode(TreeNode* node_ = NULL,int height_ = 0,TreeHeightNode* parent_ =NULL): node(node_), height(height_),parent(parent_){}
};

int getDistanceBetweenNode(TreeNode* root,TreeNode* a, TreeNode* b){
    if(root == NULL ) return -1;
    queue<TreeHeightNode *> que;
    que.push(new TreeHeightNode(root,0));
    bool flagA = false, flagB = false;
   // int heightA = 0, heightB = 0;
    TreeHeightNode* heightA =NULL, *heightB = NULL;
    while(!que.empty()){
        TreeHeightNode* tmp = que.front(); que.pop();
        TreeNode *node = tmp->node;
        if(node == a) {flagA = true;heightA = tmp;}
        if(node == b) {flagB = true;heightB = tmp;}
        if(flagA && flagB) break;
        if(node->left){
            if(node->val == 0) que.push(new TreeHeightNode(node->left,1,tmp));
            else if(node->val > 0) que.push(new TreeHeightNode(node->left,tmp->height+1,tmp));
            else if(node->val < 0) que.push(new TreeHeightNode(node->left,tmp->height-1,tmp));
        }
        if(node->right){
            if(node->val == 0) que.push(new TreeHeightNode(node->right,-1,tmp));
            else if(node->val > 0) que.push(new TreeHeightNode(node->right,tmp->height+1,tmp));
            else if(node->val < 0) que.push(new TreeHeightNode(node->right,tmp->height-1,tmp));
        }
    }
    
    if(!flagA || !flagB) return -1;
    else{
        int ha = heightA->height, hb =heightB->height;
       if(ha*hb <=0)  return ha-hb;
       else{
           if((ha >= hb && hb > 0) || (ha < hb && hb < 0)){
               int cnt = ha-hb;
               while(cnt-->0){
                   heightA=heightA->parent;
               }
               if(heightA == heightB) return ha-hb;
               else return ha-hb+2;
           }else{
               int cnt = hb - ha;
               while(cnt-- > 0){
                   heightB=heightB->parent;
               }
               if(heightB == heightA) return hb-ha;
               else return hb-ha+2;
           }
       }  
    }
}

int main(){
    TreeNode *root = new TreeNode(1);
    TreeNode *left = new TreeNode(2);
    TreeNode *right = new TreeNode(3);
    root->left = left;
    root->right = right;
    TreeNode *left1 = new TreeNode(4);
    TreeNode *right1 = new TreeNode(5);
    left->left = left1;
    left->right = right1;
    TreeNode *left2 = new TreeNode(4);
    TreeNode *right2 = new TreeNode(5);
    left1->left = left2;
    left1->right = right2;
    cout<<getDistanceBetweenNode(root,left2,right)<<endl;
    return 0;
}
View Code

其實尋找兩個結點的距離就是求兩個結點的公共祖先結點,所以另一種方法是找到o最小其公共祖先結點

然後

 

相關文章