2019 美团点评校招 图的遍历
实现代码
基于深度搜索思想,每放入一个元素,路程+1;弹出一个元素,路程+1,当遍历完所有元素后,路程不在增加。
// An highlighted block
package codingTest_1;
import java.util.Arrays;
import java.util.Scanner;
import java.util.Stack;
public class 图_遍历 {
public static class Vertex{
public Integer value;
public boolean visited;
public Vertex(int i){
this.value = i;
}
public int getValue(){
return this.value;
}
}
static int N ;// 数字个数
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
N = sc.nextInt();
int[][] adjMat = new int[N][N];// 关系矩阵
// 保存节点
Vertex[] arr = new Vertex[N];
for(int i= 0 ; i< N; i++){arr[i]= new Vertex(i);}
// 添加连线关系
// 注意:只执行n-1次 ; i<N-1 从0开始计数,共n-1次
for(int i= 0 ; i< N-1; i++){
int n1 = sc.nextInt();
int n2 = sc.nextInt();
addLine(adjMat,arr,n1,n2);
}
//for(int[] i:adjMat){System.out.println(Arrays.toString(i));}
// 深度搜索(统计次数)
int result = dpSerch(adjMat,arr);
System.out.println(result);
}
private static int dpSerch(int[][] adjMat, Vertex[] arr) {
int currentIndex=0;//当前元素指针
Stack<Integer> stack = new Stack<Integer>();// 栈,存放元素
stack.push(0);// 存入第一个元素下标
arr[0].visited = true;//把第一个元素标记为已访问
int sign = 0;// 标记,用来标记所有元素均找到的状态,(注意:都找到了但还需要把先入栈的元素弹出)
int times = 0; // 标记-查找所有元素所需的最短路程
out:while(!stack.isEmpty()){
for(int i=currentIndex+1 ; i< N ; i++){
// 有连续的点
if(adjMat[currentIndex][i] == 1 && arr[i].visited == false){
// 连续点,下标进栈
stack.push(i);
arr[i].visited = true;//标记为已访问
//System.out.println("存入:"+arr[i].getValue()+" 下标: "+i);
times++;
//System.out.println("路程+1,现在为:"+times);
currentIndex = i;//必须加,加了后查找路程变长,但不加会导致无法完全找到元素
// 作用是当找到元素相连的下一个元素后,从下一个元素开始向后找
continue out;// 应该加上,找到相邻且相连元素,指针下移,跳出循环,开始找下一层相连关系
// 综上,currentIndex = i;continue out;都应该加上
// 他俩一起可以实现依次向后找一个元素,看两个元素是否相连,如果相连,currentIndex+1,用continue跳出while循环
// 再进入while后 ,for循环指针i加1,从连接矩阵的下一层开始寻找。
// 实现效果即每一层都看后面相邻元素是否相连,相连则下移一层,继续寻找。并把找到的元素标记&&存起来。
// 如果相邻的没有相连,则跳出for循环,把最后一个元素弹出去。即 stack.pop();
// 再把指针指向上一个进栈的元素,即 currentIndex = stack.peek();
// 于是,回到上一个进栈元素层,查看adjMat中联通关系,虽然后面相邻元素是联通的,但后面这个点刚才已经被标记为已访问,故会跳过后面相邻元素,向后查找。
// 于是,通过这种方式便实现了深度搜索的理论。
}
}
// 查找完与当前点所有连续的点,弹出当前点
int pop = stack.pop();
System.out.println("弹出:"+" "+arr[pop].getValue()+" 下标: "+pop);
// 弹出点 == N,即表明点已经找完,但是后续会继续弹出先入栈的点,所以需要用标记
// 注意:弹出的点是指针,与数组长度比较需要+1
if(pop == N-1){
//System.out.println("数组长度: "+N);
sign = 1;}
if(sign != 1){
times++;
//System.out.println("路程+1,现在为:"+times);
}
// 最后一次弹栈后,栈为空,直接peek()会报错,所以加上if语句
if(!stack.isEmpty()){currentIndex = stack.peek();}
}
return times;
}
private static void addLine(int[][] adjMat,Vertex[] arr, int n1, int n2) {
// TODO Auto-generated method stub
int rowIndex =0;// 行下标
int colIndex =0;// 列下标
int i = 0;
int j=0;
for(; i<N; i++ ){
if(arr[i].getValue()== n1){break;}
rowIndex = i;
}
for(; j<N; j++ ){
if(arr[j].getValue() == n2){break;}
colIndex = j;
}
// 行列互相联通
adjMat[rowIndex][colIndex]=1;
adjMat[colIndex][rowIndex]=1;
// 自己联通自己
adjMat[rowIndex][rowIndex]=1;
adjMat[colIndex][colIndex]=1;
}
}
测试结果:
但是,测试通过率只有20%,报数组越界,暂时还没想到解决办法。先发出来,各位大神有解决方法的欢迎留言。