玩轉算法面試:(六)二叉樹和遞歸

111. 二叉樹的最小深度

給定一個二叉樹,找出其最小深度。

最小深度是從根節點到最近葉子節點的最短路徑上的節點數量。

說明: 葉子節點是指沒有子節點的節點。

示例:

給定二叉樹 [3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7

返回它的最小深度  2.

class Solution {
public:
    int minDepth(TreeNode* root) {
        if(root == NULL)
            return 0;
        if(root->left == NULL && root->right != NULL)
        {
            return 1+minDepth(root->right);
        }
        if(root->left != NULL && root->right == NULL)
        {
            return 1+minDepth(root->left);
        }
        
        return min(minDepth(root->right), minDepth(root->left))+1;
    }
};

226. 翻轉二叉樹

翻轉一棵二叉樹。

示例:

輸入:

     4
   /   \
  2     7
 / \   / \
1   3 6   9

輸出:

     4
   /   \
  7     2
 / \   / \
9   6 3   1

class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        if(root == NULL)
            return root;
        
        swap(root->left, root->right);
        invertTree(root->left);
        invertTree(root->right);
        
        return root;
    }
};

非遞歸解法

class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        if(root == NULL)
            return root;
        
        stack<TreeNode*> Tstack;
        Tstack.push(root);
        while(!Tstack.empty())
        {
            TreeNode* p = Tstack.top();
            Tstack.pop();
            
            if(p->left || p->right)
                swap(p->left, p->right);
            if(p->left)
                Tstack.push(p->left);
            if(p->right)
                Tstack.push(p->right);
        }
        
        return root;
    }
};

100. 相同的樹

給定兩個二叉樹,編寫一個函數來檢驗它們是否相同。

如果兩個樹在結構上相同,並且節點具有相同的值,則認爲它們是相同的。

示例 1:

輸入:       1         1
          / \       / \
         2   3     2   3

        [1,2,3],   [1,2,3]

輸出: true

示例 2:

輸入:      1          1
          /           \
         2             2

        [1,2],     [1,null,2]

輸出: false

示例 3:

輸入:       1         1
          / \       / \
         2   1     1   2

        [1,2,1],   [1,1,2]

輸出: false

class Solution {
public:
    bool isSameTree(TreeNode* p, TreeNode* q) {
        if(p == NULL && q == NULL)
            return true;
        if(p == NULL || q == NULL || p->val != q->val)
            return false;
        
        return isSameTree(p->left, q->left) && isSameTree(p->right, q->right);
    }
};

101. 對稱二叉樹

給定一個二叉樹,檢查它是否是鏡像對稱的。

例如,二叉樹 [1,2,2,3,4,4,3] 是對稱的。

    1
   / \
  2   2
 / \ / \
3  4 4  3

但是下面這個 [1,2,2,null,3,null,3] 則不是鏡像對稱的:

    1
   / \
  2   2
   \   \
   3    3

class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        if(!root)
            return true;
        return helper(root->left, root->right);
    }
    bool helper(TreeNode *left, TreeNode *right)
    {
        if(!left && !right)
            return true;
        else if(left && right && left->val == right->val)
            return helper(left->left, right->right) && helper(left->right, right->left);
        else
            return false;
    }
};

222. 完全二叉樹的節點個數

給出一個完全二叉樹,求出該樹的節點個數。

說明:

完全二叉樹的定義如下:在完全二叉樹中,除了最底層節點可能沒填滿外,其餘每層節點數都達到最大值,並且最下面一層的節點都集中在該層最左邊的若干位置。若最底層爲第 h 層,則該層包含 1~ 2h 個節點。

示例:

輸入:
    1
   / \
  2   3
 / \  /
4  5 6

輸出: 6

class Solution {
public:
    int countNodes(TreeNode* root) {
        int hleft = 0, hright = 0;
        TreeNode* left = root, *right = root;
        while(left)
        {
            hleft++;
            left = left->left;
        }
        while(right)
        {
            hright++;
            right = right->right;
        }
        if(hleft == hright)
            return pow(2, hleft) - 1;
        return countNodes(root->left) + countNodes(root->right) + 1;
    }
};

計算任何樹的結點個數

class Solution {
public:
    int countNodes(TreeNode* root) {
        if(root == NULL)
            return 0;
        
        int left = countNodes(root->left);
        int right = countNodes(root->right);
        
        return left + right + 1;
    }
};

110. 平衡二叉樹

給定一個二叉樹,判斷它是否是高度平衡的二叉樹。

本題中,一棵高度平衡二叉樹定義爲:

    一個二叉樹每個節點 的左右兩個子樹的高度差的絕對值不超過1。

示例 1:

給定二叉樹 [3,9,20,null,null,15,7]

    3
   / \
  9  20
    /  \
   15   7

返回 true 。

示例 2:

給定二叉樹 [1,2,2,3,3,null,null,4,4]

       1
      / \
     2   2
    / \
   3   3
  / \
 4   4

返回 false 。

class Solution {
public:
    int depth(TreeNode* root)
    {
        if(root == NULL)
            return 0;
        return max(depth(root->left), depth(root->right)) + 1;
    }
    bool isBalanced(TreeNode* root) {
        if(!root)
            return true;
        if(abs(depth(root->left) - depth(root->right)) > 1)
            return false;
        return isBalanced(root->left) && isBalanced(root->right);
    }
};
class Solution {
public:
    bool isBalanced(TreeNode* root) {
        if(checkTree(root) != -1)
            return true;
        return false;
    }
    int checkTree(TreeNode *root)
    {
        if(!root)
            return 0;
        int left = checkTree(root->left);
        int right = checkTree(root->right);
        if(abs(left - right) > 1 || left < 0 || right < 0)
            return -1;
        return max(left, right) +1;
    }
};

112. 路徑總和

給定一個二叉樹和一個目標和,判斷該樹中是否存在根節點到葉子節點的路徑,這條路徑上所有節點值相加等於目標和。

說明: 葉子節點是指沒有子節點的節點。

示例:
給定如下二叉樹,以及目標和 sum = 22,

              5
             / \
            4   8
           /   / \
          11  13  4
         /  \      \
        7    2      1

返回 true, 因爲存在目標和爲 22 的根節點到葉子節點的路徑 5->4->11->2。

class Solution {
public:
    bool hasPathSum(TreeNode* root, int sum) {
        if(!root)
            return false;
        if(!root->left && !root->right)
            return root->val == sum ;
        return hasPathSum(root->left, sum - root->val) || hasPathSum(root->right, sum - root->val);
    }
};

404. 左葉子之和

計算給定二叉樹的所有左葉子之和。

示例:

    3
   / \
  9  20
    /  \
   15   7

在這個二叉樹中,有兩個左葉子,分別是 9 和 15,所以返回 24

class Solution {
public:
    void helper(TreeNode* root, int &sum)
    {
        if(root == NULL)
            return;
        if(root->left && root->left->left == NULL && root->left->right == NULL)
            sum = sum + root->left->val;
        helper(root->left, sum);
        helper(root->right, sum);
    }
    int sumOfLeftLeaves(TreeNode* root) {
        int sum = 0;
        helper(root, sum);
        return sum;
    }
};

257. 二叉樹的所有路徑

給定一個二叉樹,返回所有從根節點到葉子節點的路徑。

說明: 葉子節點是指沒有子節點的節點。

示例:

輸入:

   1
 /   \
2     3
 \
  5

輸出: ["1->2->5", "1->3"]

解釋: 所有根節點到葉子節點的路徑爲: 1->2->5, 1->3

第一種方法遞歸

class Solution {
public:
    void dfs(TreeNode* root, vector<string> &ret, string temp)
    {
        if(root->left == NULL & root->right == NULL)
        {
            ret.push_back(temp);
            return ;
        }
        if(root->left)
            dfs(root->left, ret, temp + "->" + to_string(root->left->val));
        if(root->right)
            dfs(root->right, ret, temp + "->" + to_string(root->right->val));
    }
    vector<string> binaryTreePaths(TreeNode* root) {
        vector<string> ret;
        
        if(root == NULL)
            return ret;
        
        dfs(root, ret, to_string(root->val));
        
        return ret;
    }
};

第二種方法DFS

class Solution {
public:
    vector<string> binaryTreePaths(TreeNode* root) {
        stack<TreeNode*> tstack;
        stack<string> path;
        vector<string> ret;
        string temp = "";
        
        if(root == NULL)
            return ret;
        tstack.push(root);
        path.push(to_string(root->val));
        while(!tstack.empty())
        {
            TreeNode* node = tstack.top();
            string temp = path.top();
            tstack.pop();
            path.pop();
            if(node->left == NULL && node->right == NULL)
            {
                ret.push_back(temp);
            }
            
            if(node->left)
            {
                tstack.push(node->left);
                path.push(temp + "->" + to_string(node->left->val));
            }
                    
            if(node->right)
            {
                path.push(temp + "->" + to_string(node->right->val));
                tstack.push(node->right);
            }
        }
        
        return ret;
    }
};

第三種方法BFS

class Solution {
public:
    vector<string> binaryTreePaths(TreeNode* root) {
        queue<TreeNode*> tqueue;
        queue<string> path;
        vector<string> ret;
        string temp = "";
        
        if(root == NULL)
            return ret;
        tqueue.push(root);
        path.push(to_string(root->val));
        while(!tqueue.empty())
        {
            TreeNode* node = tqueue.front();
            string temp = path.front();
            tqueue.pop();
            path.pop();
            if(node->left == NULL && node->right == NULL)
            {
                ret.push_back(temp);
            }
            
            if(node->left)
            {
                tqueue.push(node->left);
                path.push(temp + "->" + to_string(node->left->val));
            }
                    
            if(node->right)
            {
                path.push(temp + "->" + to_string(node->right->val));
                tqueue.push(node->right);
            }
        }
        
        return ret;
    }
};

第四種方法

class Solution {
public:
    vector<string> binaryTreePaths(TreeNode* root) {
        vector<string> ret;
        
        if(root == NULL)
            return ret;
        
        if(root->left==NULL && root->right==NULL)
        {
            ret.push_back(to_string(root->val));
            return ret;
        }
        
        vector<string> left = binaryTreePaths(root->left);
        for(int i = 0; i < left.size(); i++)
        {
            ret.push_back(to_string(root->val) + "->" + left[i]);
        }
        vector<string> right = binaryTreePaths(root->right);
        for(int i = 0; i < right.size(); i++)
        {
            ret.push_back(to_string(root->val) + "->" + right[i]);
        }
        
        return ret;
    }
};

113. 路徑總和 II

給定一個二叉樹和一個目標和,找到所有從根節點到葉子節點路徑總和等於給定目標和的路徑。

說明: 葉子節點是指沒有子節點的節點。

示例:
給定如下二叉樹,以及目標和 sum = 22,

              5
             / \
            4   8
           /   / \
          11  13  4
         /  \    / \
        7    2  5   1

返回:

[
   [5,4,11,2],
   [5,8,4,5]
]

思路:分別往左子樹,右子樹遞歸遍歷所有路徑,每次遞歸就減去相應的節點值,到了葉子結點如果剩餘值與葉子結點值相等,則該條路徑符合要求,記錄下該條路徑,不符合的中間結果就pop掉。

class Solution {
public:
    void helper(TreeNode* root, int sum, vector<int> &temp, vector<vector<int>> &ret)
    {
        if(!root)
            return;
        temp.push_back(root->val);
        if(root->left == NULL && root->right == NULL && root->val == sum)
        {
            ret.push_back(temp);
        }
        
        helper(root->left, sum-root->val, temp, ret);
        helper(root->right, sum-root->val, temp, ret);
        temp.pop_back();
    }
    vector<vector<int>> pathSum(TreeNode* root, int sum) {
        vector<int> temp;
        vector<vector<int>>ret;
        helper(root, sum, temp, ret);
        return ret;
    }
};

129. 求根到葉子節點數字之和

給定一個二叉樹,它的每個結點都存放一個 0-9 的數字,每條從根到葉子節點的路徑都代表一個數字。

例如,從根到葉子節點路徑 1->2->3 代表數字 123。

計算從根到葉子節點生成的所有數字之和。

說明: 葉子節點是指沒有子節點的節點。

示例 1:

輸入: [1,2,3]
    1
   / \
  2   3
輸出: 25
解釋:
從根到葉子節點路徑 1->2 代表數字 12.
從根到葉子節點路徑 1->3 代表數字 13.
因此,數字總和 = 12 + 13 = 25.

示例 2:

輸入: [4,9,0,5,1]
    4
   / \
  9   0
 / \
5   1
輸出: 1026
解釋:
從根到葉子節點路徑 4->9->5 代表數字 495.
從根到葉子節點路徑 4->9->1 代表數字 491.
從根到葉子節點路徑 4->0 代表數字 40.
因此,數字總和 = 495 + 491 + 40 = 1026.

思路:分別往左子樹,右子樹遞歸遍歷所有路徑。到葉子節點算出數組中的值

class Solution {
public:
    void helper(TreeNode* root, vector<int> &temp, int &sum)
    {
        if(!root)
            return;
        temp.push_back(root->val);
        if(root->left == NULL && root->right == NULL)
        {
            int ret = 0;
            for(int i = 0; i < temp.size();i++)
                ret = ret*10 + temp[i];
            sum = sum + ret;
        }
        
        helper(root->left, temp, sum);
        helper(root->right, temp, sum);
        temp.pop_back();
    }
    
    int sumNumbers(TreeNode* root) {
        if(root == NULL)
            return 0;
        vector<int> temp;
        int sum = 0;
        helper(root, temp, sum);
        return sum;
    }
};

437. 路徑總和 III

給定一個二叉樹,它的每個結點都存放着一個整數值。

找出路徑和等於給定數值的路徑總數。

路徑不需要從根節點開始,也不需要在葉子節點結束,但是路徑方向必須是向下的(只能從父節點到子節點)。

二叉樹不超過1000個節點,且節點數值範圍是 [-1000000,1000000] 的整數。

示例:

root = [10,5,-3,3,2,null,11,3,-2,null,1], sum = 8

      10
     /  \
    5   -3
   / \    \
  3   2   11
 / \   \
3  -2   1

返回 3。和等於 8 的路徑有:

1.  5 -> 3
2.  5 -> 2 -> 1
3.  -3 -> 11

class Solution {
public:
    int helper(TreeNode* node, int sum)
    {
        if(node == NULL)
            return 0;
        
        int res = 0;
        if(node->val == sum)
            res = res+1;
        res += helper(node->left, sum-node->val);
        res += helper(node->right, sum-node->val);
        
        return res;
    }
    int pathSum(TreeNode* root, int sum) {
        if(root == NULL)
            return 0;
        
        int res = helper(root, sum);//以根節點爲起始點的和爲sum的路徑
        res += pathSum(root->left, sum);//左右子樹和爲sum的路徑
        res += pathSum(root->right, sum);
        
        return res;
    }
};

235. 二叉搜索樹的最近公共祖先

給定一個二叉搜索樹, 找到該樹中兩個指定節點的最近公共祖先。

百度百科中最近公共祖先的定義爲:“對於有根樹 T 的兩個結點 p、q,最近公共祖先表示爲一個結點 x,滿足 x 是 p、q 的祖先且 x 的深度儘可能大(一個節點也可以是它自己的祖先)。”

例如,給定如下二叉搜索樹:  root = [6,2,8,0,4,7,9,null,null,3,5]

 

示例 1:

輸入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8
輸出: 6
解釋: 節點 2 和節點 8 的最近公共祖先是 6。

示例 2:

輸入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4
輸出: 2
解釋: 節點 2 和節點 4 的最近公共祖先是 2, 因爲根據定義最近公共祖先節點可以爲節點本身。

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(!root)
            return NULL;
        
        if(root->val < p->val && root->val < q->val)
            return lowestCommonAncestor(root->right, p, q);
        if(root->val > p->val && root->val > q->val)
            return lowestCommonAncestor(root->left, p, q);
        
        return root;
    }
};
class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(!root)
            return NULL;
        while(root)
        {
            if(root->val < p->val && root->val < q->val)
                root= root->right;
            else if(root->val > p->val && root->val > q->val)
                root = root->left;
            else
                return root;
        }
        return NULL;
    }
};

98. 驗證二叉搜索樹

給定一個二叉樹,判斷其是否是一個有效的二叉搜索樹。

假設一個二叉搜索樹具有如下特徵:

    節點的左子樹只包含小於當前節點的數。
    節點的右子樹只包含大於當前節點的數。
    所有左子樹和右子樹自身必須也是二叉搜索樹。

示例 1:

輸入:
    2
   / \
  1   3
輸出: true

示例 2:

輸入:
    5
   / \
  1   4
     / \
    3   6
輸出: false
解釋: 輸入爲: [5,1,4,null,null,3,6]。
     根節點的值爲 5 ,但是其右子節點值爲 4 。

第一種方法:我們需要在遍歷樹的同時保留結點的上界與下界,在比較時不僅比較子結點的值,也要與上下界比較

class Solution {
public:
    bool dfs(TreeNode *root, long min, long max)
    {
        if(!root)
            return true;
        if(root->val <= min || root->val >= max)
            return false;
        return dfs(root->left, min, root->val) && dfs(root->right, root->val, max);
    }
    bool isValidBST(TreeNode* root) {
        return dfs(root, LONG_MIN, LONG_MAX);
    }
};

第二種方法:中序遍歷,採用迭代法中序遍歷

class Solution {
public:
    bool isValidBST(TreeNode* root) {
        
        stack<TreeNode*> tstack;
        long flag = LONG_MIN;
        
        while(!tstack.empty() || root != NULL)
        {
            while(root)
            {
                tstack.push(root);
                root= root->left;
            }
            
            root = tstack.top();
            tstack.pop();
            if(root->val <= flag)
                return false;
            flag = root->val;
            root = root->right;
        }
        
        return true;
    }
};

450. 刪除二叉搜索樹中的節點

給定一個二叉搜索樹的根節點 root 和一個值 key,刪除二叉搜索樹中的 key 對應的節點,並保證二叉搜索樹的性質不變。返回二叉搜索樹(有可能被更新)的根節點的引用。

一般來說,刪除節點可分爲兩個步驟:

    首先找到需要刪除的節點;
    如果找到了,刪除它。

說明: 要求算法時間複雜度爲 O(h),h 爲樹的高度。

示例:

root = [5,3,6,2,4,null,7]
key = 3

    5
   / \
  3   6
 / \   \
2   4   7

給定需要刪除的節點值是 3,所以我們首先找到 3 這個節點,然後刪除它。

一個正確的答案是 [5,4,6,2,null,null,7], 如下圖所示。

    5
   / \
  4   6
 /     \
2       7

另一個正確答案是 [5,2,6,null,4,null,7]。

    5
   / \
  2   6
   \   \
    4   7

刪除的節點有三種情況

  1.     刪除的節點無子節點。直接刪除該節點
  2.     刪除的節點有且僅有一個子節點。子節點替換刪除節點
  3.     刪除的節點同時有兩個節點。一種是從刪除節點的右分支查找最小值,賦值給刪除節點,再去右分支刪除找到的這個最小值;另一種是從刪除節點的左分支查找最大值,賦值給刪除節點,再去左分支刪除這個最大值。
class Solution {
public:
    TreeNode* deleteNode(TreeNode* root, int key) {
        if(root == NULL)
            return NULL;
        if(root->val > key)
            root->left = deleteNode(root->left, key);
        else if(root->val < key)
            root->right = deleteNode(root->right, key);
        else
        {
            if(root->left && root->right)
            {
                TreeNode * temp = root->right;
                while(temp->left)
                    temp = temp->left;
                root->val = temp->val;
                root->right = deleteNode(root->right, temp->val);
            }
            else
            {
                TreeNode *temp = root;
                if(!root->left)
                    root = root->right;
                else if(!root->right)
                    root = root->left;
                delete temp;
            }
        }
        return root;
    }
};

108. 將有序數組轉換爲二叉搜索樹

將一個按照升序排列的有序數組,轉換爲一棵高度平衡二叉搜索樹。

本題中,一個高度平衡二叉樹是指一個二叉樹每個節點 的左右兩個子樹的高度差的絕對值不超過 1。

示例:

給定有序數組: [-10,-3,0,5,9],

一個可能的答案是:[0,-3,9,-10,null,5],它可以表示下面這個高度平衡二叉搜索樹:

      0
     / \
   -3   9
   /   /
 -10  5

思路:找到數組的中點作爲樹的根節點,遞歸數組的左半邊和右半邊,分別作爲樹的左子樹和右子樹。

class Solution {
public:
    TreeNode* sortedArrayToBST(vector<int>& nums) {
        return binaryBuildTree(nums, 0, nums.size()-1);
    }
    TreeNode *binaryBuildTree(vector<int> nums, int left, int right)
    {
        if(left > right)
            return NULL;
        int mid = (left + right) /2;
        TreeNode *cur = new TreeNode(nums[mid]);
        cur->left = binaryBuildTree(nums, left, mid - 1);
        cur->right = binaryBuildTree(nums, mid+1, right);
        return cur;
    }
};

230. 二叉搜索樹中第K小的元素

給定一個二叉搜索樹,編寫一個函數 kthSmallest 來查找其中第 k 個最小的元素。

說明:
你可以假設 k 總是有效的,1 ≤ k ≤ 二叉搜索樹元素個數。

示例 1:

輸入: root = [3,1,4,null,2], k = 1
   3
  / \
 1   4
  \
   2
輸出: 1

示例 2:

輸入: root = [5,3,6,2,4,null,null,1], k = 3
       5
      / \
     3   6
    / \
   2   4
  /
 1
輸出: 3

第一種方法:使用遞歸的方法求出左子樹的節點個數,個數等於k-1就返回根節點,大於就去左子樹尋找,小於就去右子樹尋找。

class Solution {
public:
    int calTreeSize(TreeNode *root)
    {
        if(root == NULL)
            return 0;
        return 1 + calTreeSize(root->left) + calTreeSize(root->right);
    }
    int kthSmallest(TreeNode* root, int k) {
        if(root == NULL)
            return -1;
        int leftsize = calTreeSize(root->left);
        if(leftsize + 1 == k)
            return root->val;
        else if(leftsize >= k)
            return kthSmallest(root->left, k);
        else
            return kthSmallest(root->right, k-leftsize-1);
    }
};

第二種方法:使用中序遍歷,求出第k個節點

class Solution {
public:
    int kthSmallest(TreeNode* root, int k) {
        if(root == NULL)
            return -1;
        stack<TreeNode*> ret;
        TreeNode *p = root;
      
        while(p != NULL || !ret.empty())
        {
            while(p)
            {
                ret.push(p);
                p = p->left;
            }
            p = ret.top();
            if(--k == 0)
                return p->val;
            ret.pop();
            p = p->right;
        }
        return -1;
    }
};

236. 二叉樹的最近公共祖先

給定一個二叉樹, 找到該樹中兩個指定節點的最近公共祖先。

百度百科中最近公共祖先的定義爲:“對於有根樹 T 的兩個結點 p、q,最近公共祖先表示爲一個結點 x,滿足 x 是 p、q 的祖先且 x 的深度儘可能大(一個節點也可以是它自己的祖先)。”

例如,給定如下二叉樹:  root = [3,5,1,6,2,0,8,null,null,7,4]

 

示例 1:

輸入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
輸出: 3
解釋: 節點 5 和節點 1 的最近公共祖先是節點 3。

示例 2:

輸入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
輸出: 5
解釋: 節點 5 和節點 4 的最近公共祖先是節點 5。因爲根據定義最近公共祖先節點可以爲節點本身。

思路:通過返回值是否爲NULL來標識是否找到相應的節點
p,q在左右子樹,當前的根節點就是公共的祖先節點;如果p,q同在左子樹或者右子樹,公共的祖先節點是p或者q

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(!root || !p || !q)
            return NULL;
        if(root == p || root == q)
            return root;
        TreeNode *parentleft = lowestCommonAncestor(root->left, p, q);
        TreeNode *parentright = lowestCommonAncestor(root->right, p, q);
        if(parentleft && parentright)
            return root;
        return parentleft ? parentleft : parentright;
    }
};

 

求二叉樹中最遠的兩個節點的距離

求兩個節點之間最遠的距離:

  1. 兩個節點都是葉子結點
  2. 一個是葉子結點一個是根節點

思路:

 

(1)如果具有最遠距離的兩個節點經過了根節點,那麼最遠的距離就是左邊最深的深度加上右邊最深的深度之和。

(2)如果具有最遠距離的兩個節點之間的路徑不經過根節點,那麼最遠的距離就在根節點的其中一個子樹上的兩個葉子結點。

int GetFarDistance()
       {
              int distance = -1;
              _Height(_root,distance);
              return distance;
       }
protected:
       int _Height(Node* root, int& distance)
       {
              if (root == NULL)
              {
                     return 0;
              }
              int leftH = _Height(root->_left);
              int rightH = _Height(root->_right);
              if (leftH+rightH > distance)
              {
                     distance = leftH + rightH;
              }
              return leftH > rightH ? leftH+1 : rightH+1;
       }

求第k層節點的個數

int get_k_level(Node* root, int k)
{
    if(root == NULL || k <= 0)
        return 0;
    
    if(root != NULL && k == 1)
        return 1;
    
    return get_k_level(root->left, k-1) + get_k_level(root->right, k-1);
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章