最近笔试遇到好多图的问题,将笔试常见的套路算法和面试中遇到的算法进行总结。。。
Dijkstra算法
问题定义:
定义无向图中(V代表图G中的顶点集合,E代表图G中边的集合),假设每条边的长度为,找到由顶点到其余各点的最短路径
算法思想:
将图中的节点分为两部分S和U,S为已求出最短路径的顶点集合,U为未确定最短路径的顶点集合。S中值为key-value对,其中key为节点,value为对应的最短路径。U中的值也为key-value对,其中key为节点,value为路径(表示S中节点到key的距离),每次将U中最小距离对应的节点添加到S中,并对应的更新U中的节点距离,重复其过程,直到U中没有节点为止
下面是自己按照这个思路实现的完整代码,如果不清楚可以看参考1:
二分图判断
这里最近遇到的一道面试题:
给出一个二分图的定义:图中的节点被涂上黑白两色,如果满足节点和其相连的节点的颜色不同,则为二分图。
问给定一个图,判断是否是二分图
算法步骤:
- 选取一个未染色的点u进行染色
- 遍历u的相邻节点v:若v未染色,则染成不同的颜色,并对v执行第2步;如果v已经染色,如果u和v颜色相同,判定不可行退出遍历
- 如果所有节点均已染色,判定为可行
参考2中给出的java版本有点累赘,这里使用BFS的python版本解决,如下:
遍历全部节点的最短路径
给定一个有n个节点,n-1条边的无向图(节点之间可通),从指定节点开始出发,问遍历完全部节点所需要的最短步数?
不管是什么类型的遍历问题,一般的的解法都是bfs和dfs,更细的,bfs一般解决的问题是最短路径问题,dfs一般解决的是最短时间的问题。
上面的题目最常规的方法就是把所有的遍历路径全部找出来,然后返回这些路径中最短的路径。这样的思路就是典型的dfs思想,于是写出如下代码:
说明:matrix为邻接矩阵
这个代码的问题是,遍历的过程中没有对出现的环进行判断,因为正常路径是允许出现环的问题的,于是我设置minRoute的初始值,对于一个路径如果一直循环,其路径必然会大于minRoute,当大于的时候,就判定其不是最短路径,也就是说我设置最后的最短路径不可能超过minRoute的初始值。
对于出现环的问题,有一个很经典的解决方法就是BFS,其原理可以这样理解:你在一个路口上前进,每前进一步都可能有多个分叉路口,于是每次遇到分叉路径,你就将自己分成多个分身,然后同时前进,知道某一个分身到达终点,其对应的路径就为最短路径,于是写下如下代码:
这样这道题的常规解法就完成了,但是遗憾的是,这样的解法并不是出题者的意图,我们想这样一个问题:从某一个起点出发,遍历完全部节点后,又回到该起点的的步数是多少呢?是节点边的个数的2倍,那么再想原问题,怎么样遍历的路径最小呢,定义起点为s1,终点为s2,起点到终点的距离为s12,我们要求的距离为s,而,显然起点和终点相聚最远的路径是最短路径,那么将原问题转换为离起点最远的节点的路径问题,于是得到如下公式:
于是写出如下代码: