2019 美团校招 Java实现图的遍历

2019 美团点评校招 图的遍历

Alt

实现代码

基于深度搜索思想,每放入一个元素,路程+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%,报数组越界,暂时还没想到解决办法。先发出来,各位大神有解决方法的欢迎留言。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值