牛客网编程题之小米Git

来源:互联网 发布:创业软件 复牌 编辑:程序博客网 时间:2024/05/22 05:18

题目描述:

题目描述

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

解题开始:

个人一开始理解题意花了一点时间,了解到这是一个求两个树节点的最近公共父节点的问题,有一个专门经典问题(LCA最近公共祖先)就是说的这个(做完才了解的知识)。

我的思路是这样的,从根节点0出发,利用DFS求出到每个节点的n条路径,然后找到indexA和indexB两条路径,进行比较,找到路径中最后一个公共结点,就是要求的结点。

代码如下:

import java.util.*;public class Solution {    /**     * 返回git树上两点的最近分割点     *      * @param matrix 接邻矩阵,表示git树,matrix[i][j] == '1' 当且仅当git树中第i个和第j个节点有连接,节点0为git树的跟节点     * @param indexA 节点A的index     * @param indexB 节点B的index     * @return 整型     */    ArrayList<ArrayList<Integer>> joinList = new ArrayList<ArrayList<Integer>>();    ArrayList<Boolean> flagList = new ArrayList<Boolean>();    int n;    public int getSplitNode(String[] matrix, int indexA, int indexB) {        n = matrix.length;        for (int i = 0; i < n; i++) {            flagList.add(false);        }        char[][] mat = new char[n][n];//得到一个二维矩阵        for(int i =0;i<n;i++){            mat[i] = matrix[i].toCharArray();        }        ArrayList<Integer> arrayList = new ArrayList<Integer>();        arrayList.add(0);        joinList.add((ArrayList<Integer>)arrayList.clone());        flagList.set(0,true);//flagList用于跳过已经检测过的结点        DFS(mat,0,arrayList);        ArrayList<Integer> arrayA = new  ArrayList<Integer>();        ArrayList<Integer> arrayB = new  ArrayList<Integer>();        for(int i=0;i<joinList.size();i++){            ArrayList<Integer> array = joinList.get(i);            int last = array.get(array.size()-1);            if(last == indexA){                arrayA = array;            }            if(last == indexB){                arrayB = array;            }        }        int result = 0;        for(int i = 0;i<arrayA.size()&&i<arrayB.size();i++){            if(arrayA.get(i)!=arrayB.get(i)){                break;            }            result = arrayA.get(i);        }        return result;    }    public void DFS(char[][] mat,int row,ArrayList<Integer> arrayList){        for(int i = 0;i<n;i++){            boolean checkValid = flagList.get(i);            if(mat[row][i]=='1'&&!checkValid){                flagList.set(i,true);                ArrayList<Integer> newArrayList = (ArrayList<Integer>)arrayList.clone();                newArrayList.add(i);                joinList.add(newArrayList);                DFS(mat,i,newArrayList);            }        }    }}

这个解法的主要问题是需要存储每条路径,而且是利用ArrayList<ArrayList<Integer>>这种数据结构,比较耗费空间。优化的方向是只根据输入的indexA和indexB求出两条路径。

下面贴一个比较好的答案:

import java.util.List;  public class Solution {      public int getSplitNode(String[] matrix, int indexA, int indexB) {          if(indexA==indexB) return indexA;                  int nodeNum = matrix.length;        int tree[] = new int[nodeNum];        boolean flag[] = new boolean[nodeNum];                 for(int i=0; i<tree.length; i++){            tree[i]=i;        }               dfs(0, tree, matrix);                  int a = indexA;        int b = indexB;                 while(tree[a]!=a){            flag[a] = true;            a = tree[a];        }                while(tree[b]!=b){            if(flag[b]){                break;            }            b = tree[b];        }                  return b;    }          public void dfs(int root, int[] tree, String[] matrix){        for(int i=0; i<tree.length; ++i){            if(matrix[root].charAt(i) == '1' && tree[i]==i && i!=0){                tree[i] = root;                dfs(i, tree, matrix);            }        }    }      }


0 0
原创粉丝点击