154、網路延遲時間
阿新 • • 發佈:2019-01-04
題目描述
有 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;*/
}