描述
Git 是一个常用的分布式代码管理工具,Git 通过树的形式记录文件的更改历史(例如示例图),树上的每个节点表示一个版本分支,工程师经常需要找到两个分支的最近的分割点。
例如示例图中 3,4 版本的分割点是 1。3,5 版本的分割点是 0。
给定一个用邻接矩阵 matrix 表示的树,请你找到版本 versionA 和 versionB 最近的分割点并返回编号。
注意:
1.矩阵中从第一行 (视为节点 0 )开始,表示与其他每个点的连接情况,例如 [01011,10100,01000,10000,10000] 表示节点 0 与节点 1 , 3 , 4相连,节点 1 与节点 0 , 2相连,其他点的以此类推。
2.并不保证是一棵二叉树,即一个节点有可能有多个后继节点,我们把节点 0 视为树的根节点。
数据范围:树上节点数量满足 1 ≤ n ≤ 100
示例图
示例1
输入:["01011","10100","01000","10000","10000"],1,2
返回值:1
示例2
输入:["0"],0,0
返回值:0
算法思路
将邻接矩阵转换为父子关系矩阵,通过一个flags数组判断父节点是否被访问过,如果两个开始求的节点往上求父节点的过程中有重复的节点,这个节点即为分割点,比如上图中的3和5,3的往上求父节点过程为3->1->0,5的往上求父节点的过程为5->2->0,两个路径在0处重叠,0即为3和5的分割点。
邻接矩阵转父子关系矩阵的过程如下所示:
如邻接矩阵
0 1 0 1 1
1 0 1 0 0
0 1 0 0 0
1 0 0 0 0
1 0 0 0 0
转换为父子关系矩阵为
0 1 0 1 1
0 0 1 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
其中这个矩阵matrix[i][j]表示节点i和节点j相接
转换过程为从第一行开始找值为1的点,第一行为头结点,只有子节点,所以如果matrix[0][i] == 1,那就将matrix[i][0]处的值设置为0,然后判断第i行的子节点,相当于深度遍历,最终矩阵中只剩下每行代表的节点的子节点的位置(即列号),以上面父子关系矩阵为例,要找2的父节点,则依次判断matrix[i][2] == 1,如果相等,则节点i就是节点2的父节点,这里matrix[1][2] == 1,所以节点1是节点2的父节点。
判断节点是否被访问过可以使用一个一维数组flags来记录,当寻找到节点i时,就将i设置为true(默认为false),当发现当前节点已经被访问过,则返回当前节点,即所求分割点
代码实现
public void setDirected(int[][] matrix, int r) {
for (int i = 0; i < matrix.length; i++) {
if (matrix[r][i] == 1) {
matrix[i][r] = 0;
setDirected(matrix, i);
}
}
}
public int setFlags(int[][] m, boolean[] flags, int version, int row) {
while (version != 0) {
if (flags[version] == true) {
return version;
} else {
flags[version] = true;
}
for (int i = 0; i < row; i++) {
if (m[i][version] == 1) {
if (flags[i] == true) {
return i;
}
if (i == 0) {
flags[i] = true;
}
version = i;
break;
}
}
}
return 0;
}
public int Git (String[] matrix, int versionA, int versionB) {
if (versionA == versionB) {
return versionA;
}
int row = matrix.length;
int column = matrix[0].length();
int[][] m = new int[row][column];
for (int i = 0; i < row; i++) {
for (int j = 0; j < column; j++) {
m[i][j] = Integer.parseInt(matrix[i].substring(j, j+1));
}
}
setDirected(m, 0);
boolean[] flags = new boolean[row];
setFlags(m, flags, versionA, row);
int res = setFlags(m, flags, versionB, row);
return res;
}