📌  相关文章
📜  节点值从1到N的二叉树的两个节点之间的距离(1)

📅  最后修改于: 2023-12-03 14:57:10.176000             🧑  作者: Mango

节点值从1到N的二叉树的两个节点之间的距离

在二叉树中,从一个节点到另一个节点的距离可以被定义为两个节点之间路径上的边数。在节点值从1到N的二叉树中,我们需要找出两个指定节点之间的距离。

解决方案

为了解决这个问题,我们需要找到两个节点的最近公共祖先(LCA),然后计算它们之间的距离。 我们可以使用深度优先搜索(DFS)来找到LCA,然后我们可以使用树的深度来计算节点之间的距离。

找到最近公共祖先

我们可以通过递归来找到两个节点的LCA。 在递归过程中,我们遍历从根节点到给定节点的路径,将路径存储在向量中。 然后,我们比较两个节点的路径,找到最后一个共同的节点。

int findLCA(TreeNode* root, int p, int q) {
    vector<int> path1, path2;
    if (!findPath(root, p, path1) || !findPath(root, q, path2)) {
        return -1;
    }
    int i;
    for (i = 0; i < min(path1.size(), path2.size()); i++) {
        if (path1[i] != path2[i]) {
            break;
        }
    }
    return path1[i - 1];
}

bool findPath(TreeNode* root, int n, vector<int>& path) {
    if (root == nullptr) {
        return false;
    }
    path.push_back(root->val);
    if (root->val == n) {
        return true;
    }
    if (findPath(root->left, n, path) || findPath(root->right, n, path)) {
        return true;
    }
    path.pop_back();
    return false;
}
计算节点之间的距离

拥有了LCA之后,我们可以使用下面这个公式计算任意两个节点p和q之间的距离:

dist(p, q) = dist(root, p) + dist(root, q) - 2 * dist(root, LCA(p, q))
int findDistance(TreeNode* root, int p, int q) {
    int lca = findLCA(root, p, q);
    int distP = findDepth(root, p);
    int distQ = findDepth(root, q);
    int distLCA = findDepth(root, lca);
    return distP + distQ - 2 * distLCA;
}
计算节点的深度

为了计算节点的深度,我们可以使用递归来遍历树。 对于每个节点,我们计算左子树和右子树的深度,并返回较大值加1。

int findDepth(TreeNode* root, int n) {
    if (root == nullptr) {
        return -1;
    }
    if (root->val == n) {
        return 0;
    }
    int leftDepth = findDepth(root->left, n);
    int rightDepth = findDepth(root->right, n);
    if (leftDepth == -1 && rightDepth == -1) {
        return -1;
    }
    return max(leftDepth, rightDepth) + 1;
}
效率分析
  • 时间复杂度:为O(N),其中N是节点的总数。我们最多深入树中两次来查找LCA和每个节点的深度。
  • 空间复杂度: O(N), 根据递归栈的大小。
示例
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 * };
 */

class Solution {
public:
    int findLCA(TreeNode* root, int p, int q) {
        vector<int> path1, path2;
        if (!findPath(root, p, path1) || !findPath(root, q, path2)) {
            return -1;
        }
        int i;
        for (i = 0; i < min(path1.size(), path2.size()); i++) {
            if (path1[i] != path2[i]) {
                break;
            }
        }
        return path1[i - 1];
    }

    bool findPath(TreeNode* root, int n, vector<int>& path) {
        if (root == nullptr) {
            return false;
        }
        path.push_back(root->val);
        if (root->val == n) {
            return true;
        }
        if (findPath(root->left, n, path) || findPath(root->right, n, path)) {
            return true;
        }
        path.pop_back();
        return false;
    }

    int findDepth(TreeNode* root, int n) {
        if (root == nullptr) {
            return -1;
        }
        if (root->val == n) {
            return 0;
        }
        int leftDepth = findDepth(root->left, n);
        int rightDepth = findDepth(root->right, n);
        if (leftDepth == -1 && rightDepth == -1) {
            return -1;
        }
        return max(leftDepth, rightDepth) + 1;
    }

    int findDistance(TreeNode* root, int p, int q) {
        int lca = findLCA(root, p, q);
        int distP = findDepth(root, p);
        int distQ = findDepth(root, q);
        int distLCA = findDepth(root, lca);
        return distP + distQ - 2 * distLCA;
    }
};