154、网络延迟时间

题目描述
有 N 个网络节点,标记为 1 到 N。

给定一个列表 times,表示信号经过有向边的传递时间。 times[i] = (u, v, w),其中 u 是源节点,v 是目标节点, w 是一个信号从源节点传递到目标节点的时间。

现在,我们向当前的节点 K 发送了一个信号。需要多久才能使所有节点都收到信号?如果不能使所有节点收到信号,返回 -1。

注意:

N 的范围在 [1, 100] 之间。
K 的范围在 [1, N] 之间。
times 的长度在 [1, 6000] 之间。
所有的边 times[i] = (u, v, w) 都有 1 <= u, v <= N 且 1 <= w <= 100。

理解了就变得很简单:
就是用一个数组表示距离,

class Solution {
    public int networkDelayTime(int[][] times, int N, int K) {
      int distance [] = new int[N+1];
		//遍历过的list
		List<Integer> already = new ArrayList<>();
		for (int i = 1; i < distance.length; i++) {
			//首先初始化时最远距离,这里使用的是Integer的最大值代替
			distance[i] = Integer.MAX_VALUE;
		}
		
		distance[K] = 0;
		int lop = 1;
		while (lop != 0) {
			lop--;
			for (int i = 0; i < times.length; i++) {
				if(distance[times[i][0]] != Integer.MAX_VALUE){
					int t = distance[times[i][1]];
					if(times[i][2] + distance[times[i][0]] < distance[times[i][1]]){
						distance[times[i][1]] = times[i][2] + distance[times[i][0]];
						lop = 1;
					}
					
					
					
				}
			}
		}
		
	//	System.out.println(Arrays.toString(distance));
		int max = distance[1];
		for (int i = 1; i < distance.length; i++) {
			int j = distance[i];
			//存在不可到达的点
			if(j==Integer.MAX_VALUE){
				return -1;
			}
			if(max < j){
				max = j;
			}
		}
        return max;
		  
    }
}

排名靠前的代码

class Solution {
    public int networkDelayTime(int[][] times, int N, int K) {
        int limit = 99999999;
        int[][] matrix = new int[N][N];
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; ++j){
                matrix[i][j] = -1;
            }
        }                                                                                                                                                                                       
        for (int[] uvw : times) {
            matrix[uvw[0] - 1][uvw[1] - 1] = uvw[2];
        }
        // Dijkstra算法
        int last_p = K - 1;
        int[] done = new int[N];
        done[last_p] = 1;

        int[] compare_buf = new int[N];
        int[] result_buf = new int[N];
        int[] front_node = new int[N];
        for (int i = 0; i < N; i++) {
            compare_buf[i] = limit;
            result_buf[i] = limit;
            front_node[i] = -1;
        }
        result_buf[K - 1] = 0;
        int maxresult = -limit;
        while (true){
            // 对last点进行遍历,更新compare_buf
            for (int i = 0; i < matrix[last_p].length; i++) {
                int v = matrix[last_p][i];
                if (done[i] == 1 || v == -1)
                    continue;
                int value = v + result_buf[last_p];
                // 松弛操作relax
                if (value < compare_buf[i]){
                    compare_buf[i] = value;
                    front_node[i] = last_p;
                }
            }
            int temp_min = limit;
            int temp_node = -1;
            for (int i = 0; i < compare_buf.length; i++) {
                int value = compare_buf[i];
                if (done[i] == 1 || value == limit)
                    continue;
                if (value < temp_min){
                    temp_min = value;
                    temp_node = i;
                }
            }
            if (temp_node == -1)
                break;
            else{
                done[temp_node] = 1;
                last_p = temp_node;
                result_buf[temp_node] = temp_min;        
                maxresult = Math.max(temp_min, maxresult);
            }
        }
        for (int d : done){
            if (d == 0)
                return -1;
        }
        return maxresult;
    }
}

第一次使用队列的问题,我刚了一个小时才知道,原来你更新了end距离后,不是根据是否遍历过来判断是否加入队列,而是就是要加入(如果队列中没有),因为你的end距离发生了变化,那么以end作为起点的距离都可能发生变化,因此就是需要加入,所有以后要认真和全面考虑问题
改过的代码如下:

 public int networkDelayTime(int[][] times, int N, int K) {
			//我理解的Dijkstra 最短路算法,首先定义一个list存放所有没有遍历的点,然后定义一个数组,存放K到各个节点的距离,N个点,长度为N+1,那么下标为
			//K的长度就是0,因为本身到本身就是0,接着我们用一个队列存放所有点的出点,在进行存放时要注意的是:已经遍历的点不能放进去
			//每次从队列中取出一个点时,我们计算该点到另一个点的距离,并且更新距离数组,之后判断是否要将目的点放入到队列,如果已经放入过那么无需放入队列,否则
			//放入队列
			//具体实现:
			//距离数组
			int distance [] = new int[N+1];
			//遍历过的list
			List<Integer> already = new ArrayList<>();
			for (int i = 1; i < distance.length; i++) {
				//首先初始化时最远距离,这里使用的是Integer的最大值代替
				distance[i] = Integer.MAX_VALUE;
			}
			
			distance[K] = 0;
			
			distance[K] = 0;
			already.add(K);
			//设置当前遍历的队列
			Queue<Integer> Traversing = new LinkedList<>();
			Traversing.offer(K);
			while (!Traversing.isEmpty()) {
				//从节点中遍历所有的点,并且更新距离数组
				//int[][] times数组是n行三列,其中第一列是起点,第二列是终点
				//从队列中取出一个点
				int tem = Traversing.poll();
			//	System.out.println("点的顺序为"+ tem);
				for (int i = 0; i < times.length; i++) {
					//times[i][0]表示的是起点
					if(times[i][0] == tem){
					//	System.out.println("当前起点为"+tem + "距离为"+ distance[tem]);
						//等于当前的起点
						//取出终点
						int end = times[i][1];
						int distem = times[i][2];
						if(distance[end] > distem + distance[tem]){
							distance[end] =  distem + distance[tem];
					//		System.out.println("当前到"+end+"点的最小距离为"+ distance[end]);
							if(!Traversing.contains(end)){
								Traversing.offer(end);
								
							}
						}
					
					}
				}
			}
			int max = distance[0];
			for (int i = 0; i < distance.length; i++) {
				int j = distance[i];
				//存在不可到达的点
				if(j==Integer.MAX_VALUE){
					return -1;
				}
				if(max < j){
					max = j;
				}
			}
			System.out.println(Arrays.toString(distance));
	        return max;
			
			
		/*	
		 * 
		 * 
		 * int lop = 1;
			while (lop != 0) {
				lop--;
				for (int i = 0; i < times.length; i++) {
					if(distance[times[i][0]] != Integer.MAX_VALUE){
						//int t = distance[times[i][1]];
						if(times[i][2] + distance[times[i][0]] < distance[times[i][1]]){
							distance[times[i][1]] = times[i][2] + distance[times[i][0]];
							lop = 1;
						}
						
						
						
					}
				}
			}
			
			System.out.println(Arrays.toString(distance));
			int max = distance[1];
			for (int i = 1; i < distance.length; i++) {
				int j = distance[i];
				//存在不可到达的点
				if(j==Integer.MAX_VALUE){
					return -1;
				}
				if(max < j){
					max = j;
				}
			}
	        return max;*/
			
			
		/*	//初始化起点为0,因为起点到起点就是0
			distance[K] = 0;
			already.add(K);
			//设置当前遍历的队列
			Queue<Integer> Traversing = new LinkedList<>();
			Traversing.offer(K);
			while (!Traversing.isEmpty()) {
				//从节点中遍历所有的点,并且更新距离数组
				//int[][] times数组是n行三列,其中第一列是起点,第二列是终点
				//从队列中取出一个点
				int tem = Traversing.poll();
			//	System.out.println("点的顺序为"+ tem);
				for (int i = 0; i < times.length; i++) {
					//times[i][0]表示的是起点
					if(times[i][0] == tem){
					//	System.out.println("当前起点为"+tem + "距离为"+ distance[tem]);
						//等于当前的起点
						//取出终点
						int end = times[i][1];
						int distem = times[i][2];
						if(distance[end] > distem + distance[tem]){
							distance[end] =  distem + distance[tem];
					//		System.out.println("当前到"+end+"点的最小距离为"+ distance[end]);
						}
						//判断是否要进入队列,进行下一次的遍历
						if(already.contains(end)){
							
						}else {
							//没有遍历过则继续
							already.add(end);
							Traversing.offer(end);
						}
					}
				}
			}
			int max = distance[0];
			for (int i = 0; i < distance.length; i++) {
				int j = distance[i];
				//存在不可到达的点
				if(j==Integer.MAX_VALUE){
					return -1;
				}
				if(max < j){
					max = j;
				}
			}
			System.out.println(Arrays.toString(distance));
	        return max;*/
	    }

猜你喜欢

转载自blog.csdn.net/qq_34446716/article/details/85698106