距离蓝桥杯还剩整整一个月(小编报的是javaB组的程序设计),由于考虑到蓝桥杯对图论的占比稍微较高,就研究了一下最短路的算法
对于我们新手而言,第一个需掌握的应该就是迪杰斯特拉算法了,(最好先掌握的bfs再来看)
有一个可视化算法的b站视频详细介绍了整个算法的过程:
整个视频大概五分钟很短一下就能理解通透
看完之后很容易就能理解这样的算法了
但是看完之后我总结的感悟是,运用到了广度优先搜索+贪心算法:
由于知道自己编码能力不足,接下来我的思路就是:
找相关题目练手
不看题解只从这两个算法自己去参透(毕竟对于贪心的理解也不是很到位)
以下就是我研究的题目:
其实我一开始看视频的时候看表有连接父节点我想到了并查集:
但是后面想了一下并查集不是都是指向父节点吗?在我的印象当中并查集的图应该长成这样:
我可能对并查集的理解不够深刻,看是否有大佬能指点0.0
所以放弃了往并查集的思想继续考虑用dfs和贪心的思想
1.首先创建一个邻接矩阵:
int INF = Integer.MAX_VALUE/2;
int[][] arr = new int[n][n];
for(int[] t:arr){
Arrays.fill(t,INF);
}
for(int[] t:times){
int x = t[0]-1;
int y =t[1]-1;
arr[x][y]=t[2];
}
为什么INF要除以二到时候再说;
2.创建一个boolean数组来检测各个节点是否遍历完成:
boolean[] used = new boolean[n];
3.创建一个int数组来储存能到达各个节点的最小权值
int[] dis = new int[n];
Arrays.fill(dis,INF);//设置所有值开始默认都为最大,即不可抵达(这里应该就能看出INF为什么要除以2了)
dis[k-1] = 0;//设置k位置的值为0因为自己到自己最短距离就为0
最终要的来了!!!!!!!
如何以两个一维数组和一个矩阵实现贪心+广搜!
for(int i = 0;i<n;i++){
int x = -1;
for(int y = 0;y<n;y++){
if(!used[y]&&(x==-1||dis[y]<dis[x])){
x=y;
}
}
used[x]=true;
for(int y = 0;y<n;y++){
dis[y]=Math.min(dis[y],dis[x]+arr[x][y]);
}
}
首先来说第一层循环:遍历所有节点
第一层内层循环:
找出能抵达的最小的权值那个还未遍历的节点的位置
第二层循环:
看着有没有像dp????对这里就用到了贪心;得到每个节点能达到的各个位置的最小距离
再仔细看看 整个算法思维是不是有点类似于dfs???不信的可以一步一步的画图推导
整体算法:
class Solution {
public int networkDelayTime(int[][] times, int n, int k) {
int INF = Integer.MAX_VALUE/2;
int[][] arr = new int[n][n];
for(int i = 0;i<n;i++){
Arrays.fill(arr[i],INF);
}
for(int[] t:times){
int x = t[0]-1;
int y =t[1]-1;
arr[x][y]=t[2];
}
boolean[] used = new boolean[n];
int[] dis = new int[n];
Arrays.fill(dis,INF);
dis[k-1]=0;
for(int i = 0;i<n;i++){
int x = -1;
for(int y = 0;y<n;y++){
if(!used[y]&&(x==-1||dis[y]<dis[x])){
x=y;
}
}
used[x]=true;
for(int y = 0;y<n;y++){
dis[y]=Math.min(dis[y],dis[x]+arr[x][y]);
}
}
int ans = dis[0];
for(int i = 0;i<n;i++){
ans = Math.max(ans,dis[i]);
}
return ans==INF?-1:ans;
}
}
当然还有一种堆优化的版本下次再发布
总的来说这一次是小编第一此发布文章,很多地方都写得很不妥当希望能指导