Google面试题 图论的问题
2018-03-19 03:56
239 查看
这道题目摘自九章算法 https://www.jiuzhang.com/article/6ai0yN/
题目是
输入与输出
这个题目本质上就是删除一个使该图内部成环的一条边,使整个图中不存在环。
这个题目我认为原文的解释有点复杂,最快的方法就是操作数组,角标代表一个顶点,角标所对应的数组的数值代表一个顶点,而角标到该角标数值的对应,我们认为是角标代表的顶点到这个数值代表的顶点的一个连接。
而我们要做的,就是将输入的边连接的顶点,通过一个数组表示出来。
具体的过程可以参考一本国外的算法书,叫 algorithm。
其中的quick find 和quick union 讲的就是怎么要操作数组来表示一棵树
然后我抽空写了一个代码小样:
package FinalStruggle;
/**
* Created by zhoumeng on 2018/3/18.
*/
public class ExtraEdge {
public static void main(String[] args){
int[][] que = {{1,2},{2,3},{3,4},{1,4},{1,5}};
int[] extra = findExtraEdge(que);
if (extra==null){
System.out.println("404");
}else{
System.out.println("{"+extra[0]+", "+extra[1]+"}");
}
}
private static int[] findExtraEdge(int[][] que){
int N = que.length;
int [] vertexes = new int[N+1];
for (int i = 1; i<=N; i++){
vertexes[i] = i; // every vertex connects itself initially
}
for(int[] edge: que){
int left = edge[0];
int right = edge[1];
// now we need to find the circle
int l_root = findRootNode(vertexes, left);
int r_root = findRootNode(vertexes, right);
if (l_root==r_root){
return edge;
}else{
vertexes[l_root] = vertexes[right];
}
}
return null;
}
private static int findRootNode(int[] vertexes, int index) {
while (vertexes[index]!=index){
index = vertexes[index];
}
return index;
}
}
其中, findRootNode 和原文中的想法有点不一样。
在原文中,他用了一个递归,通过每次将得到的root值返回赋予当前节点这个操作,我们可以把所有连接到相同根结点角标所对应的值,都改成该根结点的角标值,这样方便之后的查找工作。
但是,这样有个缺点就是,我们没有办法知道整个树的层次,只能知道某个节点的根结点,所以代码解决的问题比较专项。
至于两相比较,时间复杂度的问题,原链接中给的代码,通过每次查询都进行值的更改,来获取下一次查询的最优状态,所以原数组的时间复杂度很稳定。我的代码,可能会形成比较深的树,在之后多次重复查询的过程中,可能会更加耗时一些。至于非常精确的时间计算,可以参考我刚才提到的algrithm一书,我记得上边给出了调用方法消耗的时间,更改数值消耗的时间和查询一次需要的时间。
因为手头暂时没有资料,而且最近真的好忙,所以没有给出具体的数据。
题目是
输入与输出
这个题目本质上就是删除一个使该图内部成环的一条边,使整个图中不存在环。
这个题目我认为原文的解释有点复杂,最快的方法就是操作数组,角标代表一个顶点,角标所对应的数组的数值代表一个顶点,而角标到该角标数值的对应,我们认为是角标代表的顶点到这个数值代表的顶点的一个连接。
而我们要做的,就是将输入的边连接的顶点,通过一个数组表示出来。
具体的过程可以参考一本国外的算法书,叫 algorithm。
其中的quick find 和quick union 讲的就是怎么要操作数组来表示一棵树
然后我抽空写了一个代码小样:
package FinalStruggle;
/**
* Created by zhoumeng on 2018/3/18.
*/
public class ExtraEdge {
public static void main(String[] args){
int[][] que = {{1,2},{2,3},{3,4},{1,4},{1,5}};
int[] extra = findExtraEdge(que);
if (extra==null){
System.out.println("404");
}else{
System.out.println("{"+extra[0]+", "+extra[1]+"}");
}
}
private static int[] findExtraEdge(int[][] que){
int N = que.length;
int [] vertexes = new int[N+1];
for (int i = 1; i<=N; i++){
vertexes[i] = i; // every vertex connects itself initially
}
for(int[] edge: que){
int left = edge[0];
int right = edge[1];
// now we need to find the circle
int l_root = findRootNode(vertexes, left);
int r_root = findRootNode(vertexes, right);
if (l_root==r_root){
return edge;
}else{
vertexes[l_root] = vertexes[right];
}
}
return null;
}
private static int findRootNode(int[] vertexes, int index) {
while (vertexes[index]!=index){
index = vertexes[index];
}
return index;
}
}
其中, findRootNode 和原文中的想法有点不一样。
在原文中,他用了一个递归,通过每次将得到的root值返回赋予当前节点这个操作,我们可以把所有连接到相同根结点角标所对应的值,都改成该根结点的角标值,这样方便之后的查找工作。
但是,这样有个缺点就是,我们没有办法知道整个树的层次,只能知道某个节点的根结点,所以代码解决的问题比较专项。
至于两相比较,时间复杂度的问题,原链接中给的代码,通过每次查询都进行值的更改,来获取下一次查询的最优状态,所以原数组的时间复杂度很稳定。我的代码,可能会形成比较深的树,在之后多次重复查询的过程中,可能会更加耗时一些。至于非常精确的时间计算,可以参考我刚才提到的algrithm一书,我记得上边给出了调用方法消耗的时间,更改数值消耗的时间和查询一次需要的时间。
因为手头暂时没有资料,而且最近真的好忙,所以没有给出具体的数据。
相关文章推荐
- Google面试题-高楼扔鸡蛋问题
- Google面试题之经典鸡蛋问题
- Google面试题-高楼扔鸡蛋问题
- 动态规划求解抛鸡蛋问题(Google某年面试题)
- Google面试题——蓄水问题
- 【动态规划】 Google面试题 爬楼梯问题 斐波那契问题的多种解法
- Google面试题——蓄水问题
- 5个广口瓶被污染的药片,没污染的药每片10mg,被污染的每片9mg,一次称重找出被污染药瓶的问题 - Google, 谷歌,百度,baidu,阿里巴巴,alibaba,微软,华为,huawei面试题
- 摔棋子(摔杯子)问题——解答Google的一道面试题
- 求子数组的最大和问题--一道浙江大学考研压轴题(被Google拿来做面试题)
- 127名选手1:1淘汰赛决出优胜者问题 - Google, 谷歌,百度,baidu,阿里巴巴,alibaba,微软,华为,huawei面试题
- Google 面试题 - 两个字符串的匹配问题(转)
- GOOGLE面试题
- [NBUT 1642 简单的图论问题?] dijkstra 模板
- 【Android问题】解决 Android SDK下载和更新失败“Connection to https://dl-ssl.google.com refused”的问题
- 2015-03-07,海盗问题----google面试第八关水平
- 微软过桥问题的图论解法
- google 面试题
- 解决“Connectionto https://dl-ssl.google.com refused”问题
- 一道有趣的面试题,小鸟和火车的问题