2019阿里校招测评题,光明小学完全图最短路径问题(python实现)
题目:光明小学的小朋友们要举行一年一度的接力跑大赛了,但是小朋友们却遇到了一个难题:设计接力跑大赛的线路,你能帮助他们完成这项工作么?
光明小学可以抽象成一张有N个节点的图,每两点间都有一条道路相连。光明小学的每个班都有M个学生,所以你要为他们设计出一条恰好经过M条边的路径。
光明小学的小朋友们希望全盘考虑所有的因素,所以你需要把任意两点间经过M条边的最短路径的距离输出出来以供参考。
你需要设计这样一个函数:
res[][] Solve( N, M, map[][]);
注意:map必然是N * N的二维数组,且map[i][j] == map[j][i],map[i][i] == 0,-1e8 <= map[i][j] <= 1e8。(道路全部是无向边,无自环)2 <= N <= 100, 2 <= M <= 1e6。要求时间复杂度控制在O(N^3*log(M))。
map数组表示了一张稠密图,其中任意两个不同节点i,j间都有一条边,边的长度为map[i][j]。N表示其中的节点数。
你要返回的数组也必然是一个N * N的二维数组,表示从i出发走到j,经过M条边的最短路径
你的路径中应考虑包含重复边的情况。
一 、求解
先来说一下求解这一题的思路,这个问题的本质就是M步无向图的最短路径遍历,一般求解最短路径问题,我们首先想到的就是采用递归实现。
已知有N个节点,求解从节点i到节点j之间的M步的最短路径问题,我们可以把M步分解成1步和M-1步:
1、假设存在节点k,且k节点不同于节点i,节点j,第一步求解节点i到节点k之间的1步最短路径
2、剩下M-1步,可以看做求解节点k到节点j之间的M-1步最短路径问题
3、当k取不同值时,我们会得到多个距离值,选取最小的一个距离值
# -*- coding: utf-8 -*- """ Created on Fri Aug 3 08:54:35 2018 @author: zy """ import numpy as np def Solve(maps,M): ''' 由N个节点两两连接组成路径,选取从节点i->节点j之间的最短M条路径 param: maps:二维数组,由两两节点之间的路径长度组成 M:表示所经过的路径个数 ''' ''' 输入校验 ''' if not isinstance(maps,(list,np.ndarray)): raise ValueError('输入参数maps数据类型必须是list或者numpy.array') if len(maps.shape) != 2: raise ValueError('输入参数maps为二维数组') if maps.shape[0] != maps.shape[1]: raise ValueError('输入二维数组maps行数和列数要求一致') #计算节点的个数 N = maps.shape[0] if N<2 or N>100: raise ValueError('输入二维数组maps行数必须在2~100之间') if M<2 or M>1E6: raise ValueError('输入参数N的值必须在2~1e6之间') #输入二维数组数值校验 for i in range(N): for j in range(i,N): if maps[i][j] != maps[j][i]: raise ValueError('输入二维数组maps必须是对称的') if maps[i][j] < -1e8 or maps[i][j] > 1e8: raise ValueError('二维数组maps的元素值必须在-1e8~1e8之间') if i==j: if maps[i][j] != 0: raise ValueError('二维数组maps的对角元素值必须是0') #用于保存i->j的路径值 res = np.zeros_like(maps) #计算节点i->j的最短路径 for i in range(N): for j in range(i,N): res[i][j] = MinPath(maps,M,i,j) res[j][i] = res[i][j] return res def MinPath(maps,M,i,j): ''' 计算i->j的最短路径 ''' #递归终止条件 if M == 1: return maps[i][j] '''计算i->j的最短路径''' N = maps.shape[0] #用于保存i->j的可能路径长度 length = np.zeros(N) #遍历从k->j的最短路径 for k in range(N): if k != i and k != j: #k->j的M-1条最短路径 + i->k的一条路径 length[k] = MinPath(maps,M-1,k,j) + maps[i][k] #进行排序,过滤掉为0的值 length = np.sort(length) for i in length: if i != 0: return i if __name__ == '__main__': #maps = np.array([[0,2,3],[2,0,1],[3,1,0]]) maps = np.array([[0,2,3,4], [2,0,1,3], [3,1,0,2], [4,3,2,0] ]) M = 3 result = Solve(maps,M) print(result)
二、时间复杂度分析
我们来分析一下该算法的时间复杂度。
先来分析一下递归函数MinPath(maps,M,i,j):
1、函数的规模为M
2、当规模是1时,函数结束
3、假设T(M)表示规模为M的问题所需要的步骤数
算法的递归方程为:T(M) = (N-2)T(M - 1) +3N+6
注释:3N+6表示规模毎减少一次,所做的步骤数
- if M==1: 1次
- N=maps.shape[0] 1次
- length = np.zeros(N) 1次
-
for k in range(N): N次
- if k != i and k != j: N次
- + maps[i][k] 当i==j时 N-1次,否则N-2次 我们取N-2次
- length = np.sort(length) 1次
- 最后的for循环 2次或者4次 我们取4次
迭代展开:T(M) = (N-2)T(M - 1) + 3N+6
亲爱的读者和支持者们,自动博客加入了打赏功能,陆陆续续收到了各位老铁的打赏。在此,我想由衷地感谢每一位对我们博客的支持和打赏。你们的慷慨与支持,是我们前行的动力与源泉。
日期 | 姓名 | 金额 |
---|---|---|
2023-09-06 | *源 | 19 |
2023-09-11 | *朝科 | 88 |
2023-09-21 | *号 | 5 |
2023-09-16 | *真 | 60 |
2023-10-26 | *通 | 9.9 |
2023-11-04 | *慎 | 0.66 |
2023-11-24 | *恩 | 0.01 |
2023-12-30 | I*B | 1 |
2024-01-28 | *兴 | 20 |
2024-02-01 | QYing | 20 |
2024-02-11 | *督 | 6 |
2024-02-18 | 一*x | 1 |
2024-02-20 | c*l | 18.88 |
2024-01-01 | *I | 5 |
2024-04-08 | *程 | 150 |
2024-04-18 | *超 | 20 |
2024-04-26 | .*V | 30 |
2024-05-08 | D*W | 5 |
2024-05-29 | *辉 | 20 |
2024-05-30 | *雄 | 10 |
2024-06-08 | *: | 10 |
2024-06-23 | 小狮子 | 666 |
2024-06-28 | *s | 6.66 |
2024-06-29 | *炼 | 1 |
2024-06-30 | *! | 1 |
2024-07-08 | *方 | 20 |
2024-07-18 | A*1 | 6.66 |
2024-07-31 | *北 | 12 |
2024-08-13 | *基 | 1 |
2024-08-23 | n*s | 2 |
2024-09-02 | *源 | 50 |
2024-09-04 | *J | 2 |
2024-09-06 | *强 | 8.8 |
2024-09-09 | *波 | 1 |
2024-09-10 | *口 | 1 |
2024-09-10 | *波 | 1 |
2024-09-12 | *波 | 10 |
2024-09-18 | *明 | 1.68 |
2024-09-26 | B*h | 10 |
2024-09-30 | 岁 | 10 |
2024-10-02 | M*i | 1 |
2024-10-14 | *朋 | 10 |
2024-10-22 | *海 | 10 |
2024-10-23 | *南 | 10 |
2024-10-26 | *节 | 6.66 |
2024-10-27 | *o | 5 |
2024-10-28 | W*F | 6.66 |
2024-10-29 | R*n | 6.66 |
2024-11-02 | *球 | 6 |
2024-11-021 | *鑫 | 6.66 |
2024-11-25 | *沙 | 5 |
2024-11-29 | C*n | 2.88 |

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了