小米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


我的思路:在读懂该题后,我认为解决该题的重点是,从indexA节点或者indexB节点向树上方走的时候其实是只有一条路的。明白这个以后就好做多了。那么我们根据邻接矩阵建立好树以后,将上溯的路径记录下来,如他的例题,1的上溯路径是1-0,   2的上溯路径是2-1-0,将这两个路径反向,既是0-1和0-1-2,然后从头上开始,如果他们相同就同时删除两个节点,第一步后剩下-1和-1-2,再删,剩下空和-2,此时发现头部已经不一样了,说明刚刚删掉的就是所求值


总结起来就3步:

1 找出所有节点的父节点

2 找出所求节点到根节点所经历的路径

3 挨个删除路径上相同的点,知道出现不同的点为止


#include<iostream>
#include<vector>
#include<string>
using namespace std;
int getSplitNode(vector<string> matrix,int indexA, int ndexB);
int main()
{
string str1 = "0001";
string str2 = "0001";
string str3 = "0001";
string str4 = "1110";
//string str5 = "10000";


vector<string> matrix;
matrix.push_back(str1);
matrix.push_back(str2);
matrix.push_back(str3);
matrix.push_back(str4);
//matrix.push_back(str5);


int indexA = 1;
int indexB = 2;
int out = getSplitNode(matrix, indexA, indexB);
cout << out;
return 0;
}
int getSplitNode(vector<string> matrix, int indexA, int indexB)
{
size_t v_s = matrix.size();
vector<int> father(v_s, -1);
vector<int> stack;
for (int i = 0; i < v_s; i++)
{
if (matrix.at(0)[i] == '1')
{
stack.push_back(i);
father.at(i) = 0;
}
}//找出0节点连着几
while (stack.size()>0)
{
for (int i = 0; i < matrix.size(); i++)
{
if ((matrix.at(stack.at(0))[i] == '1') && (i != father.at(stack.at(0))))
{
father.at(i) = stack.at(0);
stack.push_back(i);
}
}
stack.erase(stack.begin());
}//找出所有节点的父节点



vector<int> indexA_up(1,indexA);
vector<int> indexB_up(1,indexB);


int now_node = indexA;
while (1)
{
if (father.at(now_node) != -1)
{
indexA_up.insert(indexA_up.begin(),father.at(now_node));
now_node = father.at(now_node);
}//向前回溯,找出从根节点到本节点的路径
else
break;
}
now_node = indexB;
while (1)
{
if (father.at(now_node) != -1)
{
indexB_up.insert(indexB_up.begin(),father.at(now_node));
now_node = father.at(now_node);
}//向前回溯,找出从根节点到本节点的路径
else
break;
}


int same = -1;
while (1)
{
if ((indexA_up.size()>0) && (indexB_up.size()>0) && (indexA_up.at(0) == indexB_up.at(0)))
{
same = indexA_up.at(0);
indexA_up.erase(indexA_up.begin());
indexB_up.erase(indexB_up.begin());
}//挨个删除相同的节点,直到出现不同的节点,说明上次删除的那个就是最近的分割点
else
break;
}


return same;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值