📌  相关文章
📜  查询二叉树的两个节点之间的距离(1)

📅  最后修改于: 2023-12-03 15:26:39.794000             🧑  作者: Mango

查询二叉树的两个节点之间的距离

在二叉树中,两个节点之间的距离可以定义为从一个节点到另一个节点的最短距离,也就是经过最少的边数。本文将介绍如何查询二叉树中的两个节点之间的距离。

方案一:递归

我们可以定义一个递归函数来查询两个节点之间的距离。假设我们要查询节点x和节点y之间的距离,我们可以先找到它们的最近公共祖先节点z,然后用x到z的距离加上y到z的距离,就是x和y之间的距离了。

我们可以使用递归函数来查找最近公共祖先节点。如果当前节点为null或者等于x或者等于y,则返回当前节点。否则,我们在左右子树中分别查找x和y的位置,如果都不为null,则说明x和y分别位于当前节点的左右子树中,当前节点就是最近公共祖先节点。如果其中一个为null,则说明x和y都在另一个子树中,继续在该子树中查找。

下面是Java语言实现代码片段:

public class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x) { val = x; }
}

public int distance(TreeNode root, TreeNode x, TreeNode y) {
    TreeNode lca = lowestCommonAncestor(root, x, y);
    int distX = findDistance(lca, x);
    int distY = findDistance(lca, y);
    return distX + distY;
}

private TreeNode lowestCommonAncestor(TreeNode root, TreeNode x, TreeNode y) {
    if (root == null || root == x || root == y) {
        return root;
    }
    TreeNode left = lowestCommonAncestor(root.left, x, y);
    TreeNode right = lowestCommonAncestor(root.right, x, y);
    if (left != null && right != null) {
        return root;
    }
    return left != null ? left : right;
}

private int findDistance(TreeNode root, TreeNode target) {
    if (root == null) {
        return -1;
    }
    if (root == target) {
        return 0;
    }
    int left = findDistance(root.left, target);
    int right = findDistance(root.right, target);
    if (left == -1 && right == -1) {
        return -1;
    }
    return left == -1 ? right + 1 : left + 1;
}

上面的代码片段中,lowestCommonAncestor函数是查找最近公共祖先节点的递归函数,findDistance函数是查找一个节点到根节点的距离的递归函数。

方案二:迭代

我们也可以使用迭代算法来查询两个节点之间的距离。我们可以先将树转化为邻接表形式,然后利用广度优先搜索算法来寻找最短路径。

具体来说,我们从节点x开始进行广度优先搜索,同时记录每个节点到根节点的距离。当我们找到节点y时,就可以计算出x和y之间的距离了。

下面是Java语言实现代码片段:

public int distance(TreeNode root, TreeNode x, TreeNode y) {
    Map<TreeNode, Integer> dist = new HashMap<>();
    Map<TreeNode, TreeNode> parent = new HashMap<>();
    Queue<TreeNode> queue = new LinkedList<>();
    dist.put(root, 0);
    parent.put(root, null);
    queue.offer(root);
    while (!queue.isEmpty()) {
        TreeNode node = queue.poll();
        if (node == x || node == y) {
            break;
        }
        if (node.left != null) {
            dist.put(node.left, dist.get(node) + 1);
            parent.put(node.left, node);
            queue.offer(node.left);
        }
        if (node.right != null) {
            dist.put(node.right, dist.get(node) + 1);
            parent.put(node.right, node);
            queue.offer(node.right);
        }
    }
    int distX = dist.get(x);
    int distY = dist.get(y);
    TreeNode ancestor = null;
    while (x != null && y != null && x != y) {
        if (distX > distY) {
            x = parent.get(x);
            distX--;
        } else if (distY > distX) {
            y = parent.get(y);
            distY--;
        } else {
            x = parent.get(x);
            y = parent.get(y);
            distX--;
            distY--;
        }
    }
    if (x != null && y != null && x == y) {
        ancestor = x;
    }
    int distZ = dist.get(ancestor);
    return distX + distY - 2 * distZ;
}

上面的代码片段中,我们使用了一个Map类型的dist来记录每个节点到根节点的距离,使用一个Map类型的parent来记录每个节点的父节点。我们同时维护一个队列queue,用来进行广度优先搜索。

总结

本文介绍了查询二叉树的两个节点之间的距离的两种方法:递归和迭代。递归方法采用了查找最近公共祖先节点的方式,迭代方法采用了广度优先搜索算法。两种方法的时间复杂度都是O(n),空间复杂度也不超过O(n)。