小米Git (转)

问题


题目描述

git是一种分布式代码管理工具,git通过树的形式记录文件的更改历史,比如: base’<–base<–A<–A’ ^ | — B<–B’ 小米工程师常常需要寻找两个分支最近的分割点,即base.假设git 树是多叉树,请实现一个算法,计算git树上任意两点的最近分割点。 (假设git树节点数为n,用邻接矩阵的形式表示git树:字符串数组matrix包含n个字符串,每个字符串由字符’0’或’1’组成,长度为n。matrix[i][j]==’1’当且仅当git树种第i个和第j个节点有连接。节点0为git树的根节点。)

输入例子:

[01011,10100,01000,10000,10000],1,2

输出例子:

1


问题解析

题意为: 一个多叉树 , 计算树上任意两点的最近分割点 ,使用邻接矩阵表示这个多叉树

例如:

这里写图片描述

图1: 节点1 与 节点2的最近分割点为节点1 ;
图2: 节点6 与 节点5的最近分割点为节点1 ;
     节点2 与 节点3的最近分割点为节点0 ;
图3: 节点3 与 节点2的最近分割点为节点3 ;

   
   
  • 1
  • 2
  • 3
  • 4
  • 5

思路

以求图1 节点1 与 节点2的最近分割点为例
1. 首先将无向的邻接矩阵,化为有向的邻接矩阵使用深度优先遍历的方法:将入度都清0,留下出度.

(1)找0的子节点 ,扫描matrix[0][?] ,发现matrix[0][1]='1',设置matrix[1][0] ='0' ,根据深度优先, 使用递归遍历1节点;
(2)发现matrix[1][2]='1' ,设置matrix[2][1]='0' ,用递归遍历节点2
(3)最后邻接矩阵就会变成有向.

   
   
  • 1
  • 2
  • 3
  • 4

邻接矩阵为:
这里写图片描述
转换后的矩阵很容易看出 0节点 是 1,3节点 的双亲,1节点 是 2节点 的双亲

2.定义一个bool数组 flags[4]={false} ;设初值为false;
要找 节点1 与 节点2 的最近分割点
(1)先找 1节点的轨迹:
先将flags[1] =true ;遍历数组matrix[i][1] ==’1’发现 i=0, 也就是1节点的双亲为0
设置flags[0] = true ;发现0已经是根节点,就不用再找双亲了
(2)接着找2节点的轨迹:
先将flags[2] =true ;遍历数组matrix[i][2]==’1’ ,发现i=1,找到2的双亲是1;
设置flags[1] =true ,这时发现flags[1]已经为true ;退出函数,返回1
这里写图片描述
再例如图2:节点6 与 节点5的最近分割点为节点1 ;
这里写图片描述


代码

#include<iostream>
#include<vector>
#include<cstring>
#include<memory>
using namespace std ;

class Solution {
public:
    /**
     * 返回git树上两点的最近分割点
     *
     * @param matrix 接邻矩阵,表示git树,matrix[i][j] == ‘1’ 当且仅当git树中第i个和第j个节点有连接,节点0为git树的跟节点
     * @param indexA 节点A的index
     * @param indexB 节点B的index
     * @return 整型
     */
    void setDirected(vector<string> &matrix ,int r);
    int setTrack(vector<string> &matrix ,bool flag[], int index);
    int getSplitNode(vector<string> matrix, int indexA, int indexB) ;

};





/*

将无向的邻接矩阵 ,转为有向的
以行为出度,将所有入度清0

转化为有向表以后就可以,根据通过matrix[?][index] ,找到index点的双亲

*/
void Solution::setDirected(vector<string> &matrix ,int r)
{
int j ;
for(j=0 ;j<matrix.size(); j++)
{
if(matrix[r][j]==‘1’ )
{
matrix[j][r]=‘0’ ;
setDirected(matrix,j) ;
}
}
}

int Solution::setTrack(vector<string> &matrix ,bool flags[], int index)
{
int j ,dex;
//判断是否标记,如果标记就说明两条轨迹重合
//当第一次调用这个函数的时候,是都没有标记的
//但是当第二次调用的时候,就会在第一重合点重复标记,这时就返回该点,退出递归
if( false==flags[index])
{
flags[index] =true ;
for(j =0; j<matrix.size() ;j++)
if( ‘1’==matrix[j][index])
{
dex = setTrack(matrix,flags,j);
break;
}
return dex ;
}
else
{
return index ;
}

}

int Solution::getSplitNode(vector<string> matrix, int indexA, int indexB)
{
bool *flags = new bool[matrix.size()];//用于轨迹标记
//先将flags数组都设为flags
memset(flags,false,sizeof(bool)*matrix.size()) ;

setDirected(matrix,<span class="hljs-number">0</span>) ;<span class="hljs-comment">//将矩阵转为有向的</span>

<span class="hljs-comment">//先找indexA的双亲,然后找双亲的双亲,形成一条轨迹</span>
setTrack(matrix,flags,indexA) ;
<span class="hljs-comment">//先找indexB的双亲,然后找双亲的双亲,形成一条轨迹,两条轨迹相遇的点就是要找的节点</span>
<span class="hljs-keyword">int</span> i = setTrack(matrix,flags,indexB) ;

<span class="hljs-keyword">delete</span> []flags ;
<span class="hljs-keyword">return</span> i ;

}

int main()
{
vector<string> matrix ;

<span class="hljs-keyword">int</span> n ;
<span class="hljs-built_in">cin</span>&gt;&gt;n ;

<span class="hljs-built_in">string</span> str ;
<span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> i=<span class="hljs-number">0</span> ;i&lt;n ;i++)
{
    <span class="hljs-built_in">cin</span>&gt;&gt;str;
    matrix.push_back(str);
}
<span class="hljs-keyword">int</span> a ,b ;
<span class="hljs-built_in">cin</span>&gt;&gt;a&gt;&gt;b ;

Solution solu ;
<span class="hljs-keyword">int</span> answer = solu.getSplitNode(matrix,a ,b) ;
<span class="hljs-built_in">cout</span>&lt;&lt;answer&lt;&lt;<span class="hljs-string">"\n"</span> ;

<span class="hljs-keyword">return</span> <span class="hljs-number">0</span> ;

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
转自: https://blog.csdn.net/native_lee/article/details/52567128

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值