两者都采用到了贪心的策略,并且两个算法都一直维护着一个数组dist (Dijkstra),lowCost(最小生成树)
其中:lowCost[i]表示:当前构建的生成树集合到顶点i的最低代价
dist [i]表示:当前节点k到各个顶点的最短路径
算法思路:
不断从不在当前最优集合中去寻找和当前最优集合的最小代价,通过当前选中的最优决策来不断更新维护该数组(dist,lowCost),直到所有顶点都被标记为止。
—直接上代码看
743. 网络延迟时间(最短路径算法)
//Dijkstra算法 :从 k 点出发,到其他点 x 的最短距离的最大值 【和Prim算法很像】
class Solution {
public int networkDelayTime(int[][] times, int n, int k) {
final int distance = Integer.MAX_VALUE>>1;
//graph初始化,邻接矩阵存储
int[][] graph = new int[n+1][n+1];
for(int i=0;i<=n;i++){
Arrays.fill(graph[i],distance); //权值距离先置为无限大
}
for(int i=0;i<=n;i++){
graph[i][i] = 0; //自己到自己为0
}
//按题目已知初始化
int len = times.length;
for(int i=0;i<len;i++){
int[] cur = times[i];
//有向图
graph[cur[0]][cur[1]] = cur[2];
}
//----------初始化完成(graph邻接矩阵)--------------
//起点为1开始
//dist[i]:表示当前顶点k到各个顶点i的最短距离
int[] dist = new int[n+1];
boolean[] visited = new boolean[n+1];
Arrays.fill(dist,distance); //dist[i] :表示k->i的距离
//从 kk 点出发,到其他点 xx 的最短距离的最大值
dist[k] = 0; //自己到自己为0
for(int c=0;c<n;c++){
//找dist最小的值
int index = -1;
int minVal = distance;
for(int i=1;i<=n;i++){
//从不在最优集合中去寻找和当前最优的数
if(!visited[i]){
if(minVal>dist[i]){
index = i;
minVal = dist[i];
}
}
}
if(index==-1){ //出度为0直接return -1;
return -1;
}
//找到了最小的,对最小的graph这一行进行展开 【出度扫描】
visited[index] = true; //收入到最优路径长度中
for(int j=1;j<=n;j++){
//dist[index]+graph[index][j]:表示能通过该最短路径作为跳板来找到dist[j]的最短路径
//不难看出只要是graph[index][j]不等于无穷大那么就一定存在值
dist[j] = Math.min(dist[j],dist[index]+graph[index][j]);
}
}
int res = -1;
for(int i=1;i<=n;i++){
res = Math.max(res,dist[i]);
}
return res;
}
}
1584. 连接所有点的最小费用(最小生成树)
class Solution {
public int minCostConnectPoints(int[][] points) {
final int max = Integer.MAX_VALUE>>1;
int size = points.length; //size个顶点
//顶点选取集合 (seelcted)
boolean[] visited = new boolean[size]; //顶点从0开始
//某一时刻
//init
int[][] g = new int[size][size];
//lowCost[i]表示:当前构建的生成树集合到顶点i的最低代价
int[] lowCost = new int[size];
for(int i=0;i<size;i++){
for(int j=0;j<size;j++){
int dict = dict(points,i,j);
//无向图
g[i][j] = dict;
g[j][i] = dict;
}
}
//----------初始化完成(g邻接矩阵)--------------
//init 选中一个点进行寻找--------------------------------------
for(int i=0;i<size;i++){
lowCost[i] = g[0][i];
}
//将第一个节点(index=0)收入最小生成树中
//表示加入到了最小生成树集合中
visited[0] = true;
int sum = 0; //记录结果
int count = 1;
while(count<size){
//找一个最低代价的顶点加入
int min = max;
int index = -1;
//选择lowCost最小值
for(int i=0;i<size;i++){
//从不在最小生成树中去寻找最小代价的节点
if(!visited[i] && min>lowCost[i]){ //没有被选择的
index = i; //最低点的下标
min = lowCost[i];
}
}
if(index==-1){
return sum; //不找了
}
sum += min;
count++;
//记为最小生成树的节点
visited[index] = true;
//更新lowCost数组
for(int i=0;i<size;i++){
if(visited[i]){
continue;
}
//不需要g[index][i]+lowCost[index]
//这里借助当前刚加入到生成树的这个顶点跳板来更新lowCost数组
lowCost[i] = Math.min(lowCost[i],g[index][i]);
}
}
return sum;
}
//自己到自己0
private int dict(int[][] points,int i,int j){
return Math.abs(points[i][0]-points[j][0]) + Math.abs(points[i][1]-points[j][1]);
}
}