Dijkstra算法思维(java)菜鸟入门

距离蓝桥杯还剩整整一个月(小编报的是javaB组的程序设计),由于考虑到蓝桥杯对图论的占比稍微较高,就研究了一下最短路的算法

对于我们新手而言,第一个需掌握的应该就是迪杰斯特拉算法了,(最好先掌握的bfs再来看)

有一个可视化算法的b站视频详细介绍了整个算法的过程:

【算法】最短路径查找—Dijkstra算法

整个视频大概五分钟很短一下就能理解通透

看完之后很容易就能理解这样的算法了

但是看完之后我总结的感悟是,运用到了广度优先搜索+贪心算法:

由于知道自己编码能力不足,接下来我的思路就是:

  • 找相关题目练手

  • 不看题解只从这两个算法自己去参透(毕竟对于贪心的理解也不是很到位)

以下就是我研究的题目:

LeetCode:743. 网络延迟时间


其实我一开始看视频的时候看表有连接父节点我想到了并查集:

但是后面想了一下并查集不是都是指向父节点吗?在我的印象当中并查集的图应该长成这样:

我可能对并查集的理解不够深刻,看是否有大佬能指点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;
        
    }
}

当然还有一种堆优化的版本下次再发布

总的来说这一次是小编第一此发布文章,很多地方都写得很不妥当希望能指导

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值