鱼C论坛

 找回密码
 立即注册
查看: 1105|回复: 3

[已解决]二叉树,设计算法求解公共祖先

[复制链接]
发表于 2023-4-8 19:46:03 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
设计算法以求解编号为i和j的两个结点的最近的公共祖先结点的编号。
最佳答案
2023-4-8 20:22:39
白痴爱面包 发表于 2023-4-8 20:19
有其他方法吗,示例用c或c++

以下是使用C++编写的另一种求解二叉树中两个结点最近公共祖先的方法。

这种方法基于向上追踪祖先结点的思路。
#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

// 计算结点的深度
int getNodeDepth(int node) {
    int depth = 0;
    while (node > 1) {
        node = node / 2;
        depth++;
    }
    return depth;
}

// 查找公共祖先
int findLowestCommonAncestor(int i, int j) {
    // 计算两个结点的深度
    int depth_i = getNodeDepth(i);
    int depth_j = getNodeDepth(j);

    // 调整深度使两个结点在同一层
    while (depth_i > depth_j) {
        i = i / 2;
        depth_i--;
    }

    while (depth_j > depth_i) {
        j = j / 2;
        depth_j--;
    }

    // 向上追踪公共祖先
    while (i != j) {
        i = i / 2;
        j = j / 2;
    }

    return i;
}

int main() {
    int i = 9;
    int j = 13;
    cout << findLowestCommonAncestor(i, j) << endl;  // 输出:2

    return 0;
}
这种方法首先计算两个结点的深度,然后调整深度使它们在同一层。

接下来,同时向上追踪两个结点的祖先,直到找到它们的公共祖先为止。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-4-8 19:49:01 | 显示全部楼层
在二叉树中,我们可以通过结点编号的二进制表示来追踪它们的祖先。对于给定的结点i和j,我们可以使用以下算法求解它们的最近公共祖先结点的编号:

  • 将结点i和j的编号分别转换为二进制表示,例如:i = 1001(二进制),j = 1101(二进制)。
  • 在二进制表示中,从最高位开始,找到第一个不同的二进制位,例如:第一个不同的二进制位在本例中是第二位。
  • 截取从最高位开始到第一个不同二进制位之前的部分,然后将其转换回十进制,得到的数就是最近公共祖先结点的编号,例如:公共祖先结点的二进制表示为10,转换为十进制后得到2。

下面是用Python实现的该算法:
def find_lowest_common_ancestor(i, j):
    # 转换为二进制表示并去掉'0b'前缀
    i_bin = bin(i)[2:]
    j_bin = bin(j)[2:]

    # 获取最短长度
    min_len = min(len(i_bin), len(j_bin))

    # 寻找第一个不同的二进制位
    diff_index = -1
    for k in range(min_len):
        if i_bin[k] != j_bin[k]:
            diff_index = k
            break

    # 如果没有找到不同的二进制位,则取最短长度作为截止点
    if diff_index == -1:
        diff_index = min_len

    # 获取公共祖先的二进制表示,并转换为十进制
    common_ancestor_bin = i_bin[:diff_index]
    common_ancestor = int(common_ancestor_bin, 2)

    return common_ancestor

# 测试
i = 9
j = 13
print(find_lowest_common_ancestor(i, j))  # 输出:2

以上算法可以高效地求解二叉树中任意两个结点的最近公共祖先结点的编号。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-4-8 20:19:02 | 显示全部楼层
isdkz 发表于 2023-4-8 19:49
在二叉树中,我们可以通过结点编号的二进制表示来追踪它们的祖先。对于给定的结点i和j,我们可以使用以下算 ...

有其他方法吗,示例用c或c++
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-4-8 20:22:39 | 显示全部楼层    本楼为最佳答案   
白痴爱面包 发表于 2023-4-8 20:19
有其他方法吗,示例用c或c++

以下是使用C++编写的另一种求解二叉树中两个结点最近公共祖先的方法。

这种方法基于向上追踪祖先结点的思路。
#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

// 计算结点的深度
int getNodeDepth(int node) {
    int depth = 0;
    while (node > 1) {
        node = node / 2;
        depth++;
    }
    return depth;
}

// 查找公共祖先
int findLowestCommonAncestor(int i, int j) {
    // 计算两个结点的深度
    int depth_i = getNodeDepth(i);
    int depth_j = getNodeDepth(j);

    // 调整深度使两个结点在同一层
    while (depth_i > depth_j) {
        i = i / 2;
        depth_i--;
    }

    while (depth_j > depth_i) {
        j = j / 2;
        depth_j--;
    }

    // 向上追踪公共祖先
    while (i != j) {
        i = i / 2;
        j = j / 2;
    }

    return i;
}

int main() {
    int i = 9;
    int j = 13;
    cout << findLowestCommonAncestor(i, j) << endl;  // 输出:2

    return 0;
}
这种方法首先计算两个结点的深度,然后调整深度使它们在同一层。

接下来,同时向上追踪两个结点的祖先,直到找到它们的公共祖先为止。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-12-22 00:40

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表