最短路径
最短路径
这玩意尊嘟很基础,但是写得少,每次遇到都会愣住,干脆写一篇记录一下
Floyed
求出的是多源最短路,时间复杂度O(n^3^),空间复杂度O(n^2^)
1
2
3
4
5
6
7
8
9
10
11
//w[i][j]表示i到j的最小路径,初始化时,邻接则填入邻接距离,否则填入Inf
for(int k = 0;k< w.length;k++){
//中间点
for(int i =0;i<w.length;i++){
//起点
for(int j =0;j<w.length;j++){
//终点
w[i][j] = Math.min(w[i][j],w[i][k]+w[k][j]);
}
}
}
注意是根据中间点为重心进行循环,先遍历中间点
3015. 按距离统计房屋对数目 I
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
class Solution {
public int[] countOfPairs(int n, int x, int y) {
int inf = Integer.MAX_VALUE/2-100;
int[][] w = new int[n+1][n+1];
for(int i =0;i<w.length;i++){
Arrays.fill(w[i],inf);
}
for(int i =1;i<w.length-1;i++){
w[i][i]=0;
w[i+1][i+1] = 0;
w[i][i+1] = 1;
w[i+1][i] = 1;
}
if(x!=y){
w[x][y] = 1;
w[y][x] = 1;
}
for(int k = 0;k< w.length;k++){
//中间点
for(int i =0;i<w.length;i++){
//起点
for(int j =0;j<w.length;j++){
//终点
w[i][j] = Math.min(w[i][j],w[i][k]+w[k][j]);
}
}
}
int[] res = new int[n];
for(int i =0;i<w.length;i++){
for(int j =0;j<w.length;j++){
if(w[i][j]-1>=0 && w[i][j]-1<res.length){
res[w[i][j]-1] ++;
}
}
}
return res;
}
}
Dijkstra
求出的是单源最短路,且权值非负。
朴素:时间复杂度O(n^2^),空间复杂度O(n^2^)
基本思路:分为已确定的点与未确定的点,每一轮拿最小dis终点当作确定点,并查看可否经过这个确定点走到未确定点可以路径更短
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
//path[i][j]表示从i到j的路径,邻接则是邻接距离,否则为Inf
long[] dis = new long[n];
Arrays.fill(dis,Long.MAX_VALUE/2);
dis[0]=0;
//dis[i]表示从0-i的最短距离,初始化时都填入Inf,dis[0]=0
boolean[] done = new boolean[n];
Arrays.fill(done,false);
//done[i]==true 表示dis[i]已经是最短路径了
while (true){
int x = -1;
for(int i =0;i<n;i++){
if(!done[i] && (x<0 || dis[i]<dis[x])){
//dis[i]没有定下,并且要找到最小的那个确定下来
x=i;
}
}
//定下,现在dis[x]是最小的dis
done[x]=true;
for(int i =0;i<n;i++){
//i为终点,x为中间,看能不能更新
long newDis = dis[x] + path[x][i];
if(newDis<dis[i]){
//能更新
dis[i] = newDis;
}
}
}
堆优化
时间复杂度:O(n*logn),如果是稠密图,则是O(n^2^ *logn)。空间复杂度:O(n)
相同思路,只不过寻找最小dis交给最小堆实现,从而查询一次的复杂度由O(n)到O(logn)
存入堆的是一个二元组(dis,x)表示从0-x的距离为dis
只有第一次出堆是最小dis
因而取消了done,并且由path变为邻接图
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
//注意:这里是邻接图
ArrayList<int[]>[] neighbour = new ArrayList[n];
for(int i =0;i<neighbour.length;i++){
neighbour[i] = new ArrayList<>();
}
long[] dis = new long[n];
Arrays.fill(dis,Long.MAX_VALUE/2);
dis[0]=0;
//dis[i]表示从0-i的最短距离,初始化时都填入Inf,dis[0]=0
PriorityQueue<Pair> queue = new PriorityQueue<>(Comparator.comparingLong(Pair::getDx));
queue.add(new Pair(0L,0));
while (true){
Pair curPair = queue.poll();
long dx = curPair.getDx();
int x = curPair.x;
//初次出堆,才是最小
if(dx > dis[x])continue;//以前出堆过
if(x==n-1) break;
for(int[] nei : neighbour[x]){
int y = nei[0];
int cur_dis = nei[1];
long newDis = dx + cur_dis;
if(newDis < dis[y]){
dis[y] = newDir;
queue.add(new Pair(dis[y],y));
}
}
}
private class Pair{
private long dx;
private int x;
public Pair(long dx,int x){
this.dx = dx;
this.x = x;
}
public long getDx(){
return dx;
}
public int getX(){
return x;
}
}
本文由作者按照 CC BY 4.0 进行授权