偶尔要写写算法,是我平时用来保持感觉的常用的方法.今天看到园子里一面试题,看了一下感觉也能实现,不过过程确实艰的,自认为自己对算法的感觉还不错.不过这题确实我也用了差不多一下午的时间,基本上把工作时间都耗掉了.主要的两个方法已经搞定,下面先说一下思想,代码确实不太重要,因为过一周我自己就会看不懂了,就像我今天也去看以前的代码.因为这里用到一部分深度优先遍历,所以去找以前代码,但是完全没有作用,还是纯写.

  

  1. interface IPath
  2. {
  3. /// <summary>
  4. /// 增加某条地铁线路
  5. /// </summary>
  6. /// <param name="lineNo">地铁线号</param>
  7. /// <param name="stationNum">站点数目</param>
  8. /// <param name="stationArray">地铁线站台号数组</param>
  9. void AddLine(int lineNo, int stationNum, int[] stationArray);
  10.  
  11. /// <summary>
  12. /// 计算从超点到终点的最短路线长度
  13. /// </summary>
  14. /// <param name="srcStation">起点站</param>
  15. /// <param name="desStation">终点站</param>
  16. /// <returns>起点站到终点站最短线长度</returns>
  17. int CalcMinPathLen(int srcStation, int desStation);
  18.  
  19. /// <summary>
  20. /// 输出从起点到终点的最短路线
  21. /// </summary>
  22. /// <param name="srcStation">起点</param>
  23. /// <param name="desStation">终点</param>
  24. /// <param name="pathNum">条数</param>
  25. /// <param name="pathLen">长度</param>
  26. /// <param name="pathes">结果路线集合</param>
  27. /// <returns>0成功 -1出错</returns>
  28. int SearchMinPaths(int srcStation, int desStation, out int pathNum, out int pathLen, out int[][] pathes);
  29.  
  30. /// <summary>
  31. /// 最优路线
  32. /// </summary>
  33. /// <param name="srcStation">起点</param>
  34. /// <param name="desStation">终点</param>
  35. /// <param name="pathNum">条数</param>
  36. /// <param name="pathLen">长度</param>
  37. /// <param name="pathes">结果路线集合</param>
  38. /// <returns>0成功 -1出错</returns>
  39. int SearchBestPathes(int srcStation, int desStation, out int pathNum, out int pathLen, out int[][] pathes);
  40.  
  41. }

其实这个从题目中命名等看出来主要是C++题,本人用C#实现,其实可以改一些参数名称更为方便,但是这里就按题目中接口来吧.AddLine方法就不说了.

  1. int CalcMinPathLen(int srcStation, int desStation);

计算最短路径,这里用的是迪杰斯特拉算法,就是从起点按起点到各各点最短距离来一个一个往集合里面添加,当然这里的距离就是1,如果是其它数字也是可以的.

  1. int SearchMinPaths(int srcStation, int desStation, out int pathNum, out int pathLen, out int[][] pathes);

这个方法其实略坑了,我基本上是重新想的解决办法,同第一个方法没有很大的联系,不知道我这种思考是否是最优的,不过是可以解决的.重点地方就是用到一个变异的深度优先遍历,这个是有环路存在的,所以比树的深度优先遍历要复杂一些,注意一下深度就可以了,用到一个深度变量去控制是不是保留在遍历排除集合中,就是方法中的list.

两个方法代码如下

  1. public class MetroPath : IPath
  2. {
  3. private readonly List<Tuple<int, int, int[]>> pathes;
  4. private int stationCount = ;
  5.  
  6. private List<int> minStations;
  7.  
  8. public MetroPath()
  9. {
  10. pathes = new List<Tuple<int, int, int[]>>();
  11. minStations = new List<int>();
  12. }
  13.  
  14. public void AddLine(int lineNo, int stationNum, int[] stationArray)
  15. {
  16. if (stationNum < || stationArray == null || stationArray.Length != stationNum)
  17. Console.WriteLine("站点数目不对");
  18. else
  19. pathes.Add(new Tuple<int, int, int[]>(lineNo, stationNum, stationArray));
  20. }
  21.  
  22. public int CalcMinPathLen(int srcStation, int desStation)
  23. {
  24. //用迪杰斯特拉算法计算
  25. Dictionary<int, int> stationLens = new Dictionary<int, int>();
  26.  
  27. IEnumerable<int> ct = pathes[].Item3;
  28. //得到所有站数
  29. foreach (var a in pathes)
  30. {
  31. ct = ct.Union(a.Item3);
  32. }
  33. stationCount = ct.Distinct().Count();
  34.  
  35. try
  36. {
  37. stationLens.Add(srcStation, );//初始
  38.  
  39. while (stationLens.Count < stationCount)
  40. {
  41. stationLens = FindMinStation(stationLens, srcStation);
  42. }
  43.  
  44. //下一题用
  45. minStations = stationLens.Select(x => x.Key).ToList();
  46.  
  47. //找出起点到终点最短长度
  48. return stationLens[desStation];
  49. }
  50. catch
  51. {
  52. return -; //出错
  53. }
  54. }
  55.  
  56. //找出余下站点中最短的站点及起点到它的长度
  57. private Dictionary<int, int> FindMinStation(Dictionary<int, int> stations, int srcStation)
  58. {
  59. Dictionary<int, int> lens = new Dictionary<int, int>();
  60.  
  61. foreach (var p in pathes)
  62. {
  63. foreach (var station in p.Item3)
  64. {
  65. if (!stations.ContainsKey(station))
  66. {
  67. //计算最小值
  68. var minlen = ReachLen(stations, srcStation, station);
  69. if (minlen > && !lens.ContainsKey(station))
  70. lens.Add(station, minlen);
  71. }
  72. }
  73. }
  74.  
  75. //找出lens中最小的(可以多个)加入集合
  76. int min = lens.Min(v => v.Value);
  77.  
  78. return stations.Union(lens.Where(x => x.Value == min)).ToDictionary(k => k.Key, v => v.Value);
  79. }
  80.  
  81. //是否是可达的 -1为不可达
  82. private int ReachLen(Dictionary<int, int> stations, int srcStatoin, int station)
  83. {
  84. List<int> reachStations = new List<int>();
  85. foreach (var p in pathes)
  86. {
  87. for (int i = ; i < p.Item3.Length; i++)
  88. {
  89. if (p.Item3[i] == station)
  90. {
  91. if (i - >= && !reachStations.Contains(p.Item3[i - ]))
  92. reachStations.Add(p.Item3[i - ]);
  93. if (i + < p.Item3.Length && !reachStations.Contains(p.Item3[i + ]))
  94. reachStations.Add(p.Item3[i + ]);
  95. }
  96. }
  97. }
  98.  
  99. var q = stations.Where(v => reachStations.Contains(v.Key));
  100. //相邻点不在集合里面
  101. if (q == null || q.Count() <= )
  102. return -;
  103. else
  104. {
  105. //找出q中最小的值
  106. return q.OrderByDescending(v => v.Value).First().Value + ;
  107. }
  108.  
  109. }
  110.  
  111. public int SearchMinPaths(int srcStation, int desStation, out int pathNum, out int pathLen, out int[][] pathes)
  112. {
  113. pathNum = ;
  114. pathLen = ;
  115. pathes = null;
  116.  
  117. try
  118. {
  119. pathLen = CalcMinPathLen(srcStation, desStation);
  120.  
  121. List<int[]> result = new List<int[]>();
  122.  
  123. Stack<int> sk1 = new Stack<int>();
  124. List<Tuple<int, int>> list = new List<Tuple<int, int>>();
  125.  
  126. sk1.Push(srcStation);
  127. minStations.Remove(srcStation);
  128.  
  129. int ct = ;
  130. int deepth = ;
  131. while (deepth > )
  132. {
  133. bool flag = false;
  134. foreach (var x in minStations)
  135. {
  136. list.RemoveAll(v => v.Item1 > deepth);
  137.  
  138. if (ExistsRalation(sk1.Peek(), x) && !sk1.Contains(x) && list.Where(v => v.Item2 == x).Count() <= )
  139. {
  140. sk1.Push(x);
  141. deepth++;
  142. flag = true;
  143. break;
  144. }
  145. }
  146.  
  147. //
  148. if (sk1.Peek() == desStation)
  149. {
  150. //一条完整的路线
  151. result.Add(sk1.Reverse().ToArray());
  152. deepth--;
  153. list.Add(new Tuple<int, int>(deepth, sk1.Pop()));
  154. ct++;
  155. }
  156. //没有找到
  157. if (!flag)
  158. {
  159. deepth--;
  160. list.Add(new Tuple<int, int>(deepth, sk1.Pop()));
  161. }
  162. }
  163.  
  164. pathNum = ct;
  165. pathes = result.ToArray();
  166. return ;
  167. }
  168. catch
  169. {
  170. return -;
  171. }
  172.  
  173. }
  174.  
  175. private bool ExistsRalation(int a, int b)
  176. {
  177. if (a == b)
  178. return false;
  179.  
  180. foreach (var p in pathes.Where(x => x.Item3.Contains(a) && x.Item3.Contains(b)))
  181. {
  182. for (int i = ; i < p.Item3.Length; i++)
  183. {
  184. if (p.Item3[i] == a)
  185. {
  186. if (i - >= && p.Item3[i - ] == b)
  187. return true;
  188. if (i + < p.Item3.Length && p.Item3[i + ] == b)
  189. return true;
  190. }
  191. }
  192. }
  193. return false;
  194.  
  195. }
  196.  
  197. public int SearchBestPathes(int srcStation, int desStation, out int pathNum, out int pathLen, out int[][] pathes)
  198. {
  199. throw new NotImplementedException();
  200. }
  201. }

最后一个方法还没有实现,不过大思路也还是可以有的,路径找出来了,只要看路径上交乘点多少就可以了,越少越优,这个算简单.没有时间写了.

最后是调用代码和结果

  1. //测试
  2. IPath mp = new MetroPath();
  3. mp.AddLine(, , new int[] { , , , , });
  4. mp.AddLine(, , new int[] { , , , , });
  5. mp.AddLine(, , new int[] { , , });
  6. mp.AddLine(, , new int[] { , });
  7.  
  8. var min = mp.CalcMinPathLen(, );
  9. Console.WriteLine("从1到11最短路径长度为:{0}", min);
  10.  
  11. int pathNum = ;
  12. int pathLen = ;
  13. int[][] pathes = null;
  14. var re = mp.SearchMinPaths(, , out pathNum, out pathLen, out pathes);
  15.  
  16. Console.WriteLine("从1到11最短路径条数为{0},分别是", pathNum);
  17. foreach (var x in pathes)
  18. {
  19. Console.Write("\n{");
  20. foreach (var i in x)
  21. {
  22. Console.Write("{0},", i);
  23. }
  24. Console.Write("}\n");
  25. }
  26.  
  27. Console.ReadLine();

对题中的数据来看是正常的.个人觉得本题还是有难度的,特别是要实实在在写出来,并且调通,我看文中评论有些说简单的人请去实践一下再说吧.

插个小插曲,就是代码一写过基本上就看不懂了.刚才我说到我查阅深度优先算法,我自己的代码完全看不懂,不过看起来以前写的还是很简练,不过是对简单图的遍历.

  1. /// <summary>
  2. /// 深度优先
  3. /// </summary>
  4. static void DFS(int[,] a, int n)
  5. {
  6. Stack<int> sk1 = new Stack<int>();
  7. Stack<int> sk2 = new Stack<int>();
  8. sk1.Push();
  9. Console.WriteLine();
  10. int x = ;//访问点标记
  11.  
  12. int ct = ;//访问节点数
  13. while (ct < n)
  14. {
  15. int i = ;
  16. bool f = false;
  17. for (i = ; i < n; i++)
  18. {
  19. if (a[x, i] != && !sk2.Contains(i))
  20. {
  21. sk1.Push(i);
  22. Console.WriteLine(i); ct++;
  23. x = i;
  24.  
  25. f = true;
  26. break;
  27. }
  28. }
  29. if (!f)
  30. {
  31. //没有找到返回
  32. sk2.Push(sk1.Pop());
  33. x = sk1.Peek();
  34. }
  35.  
  36. }
  37. }

确实比较短的,不过看不懂.所以主要还是在于思想吧.数据测试

  1. int[,] a = {
  2. {,,,,}
  3. ,{,,,,}
  4. ,{,,,,}
  5. ,{,,,,}
  6. ,{,,,,}
  7. };
  8.  
  9. Console.WriteLine("DFS:");
  10. DFS(a, );
  11. Console.Read();

  最后总结:  

    1.理解迪杰斯特拉算法

    2.深度优先遍历,主要用栈,广度优先主要考虑队列.

    3.深度优先的冲突处理,考虑用深度变量.

<<薪资至少10K的一道题,你能拿下吗>>练习的更多相关文章

  1. 薪资至少10K的一道题,你能拿下吗

    我所了解的华为: 应届本科生8k+ 应届硕士生10k+ 应届博士生12k+ 看到后什么感想?有没有只恨生不逢时运不佳的感觉? 很多人做3年多甚至更久,才能达到这个薪资水平,还不如一个新生. 在我看来, ...

  2. 盘点一下Github上开源的Java面试/学习相关的仓库,看完弄懂薪资至少增加10k

    最近浏览 Github ,收藏了一些还算不错的 Java面试/学习相关的仓库,分享给大家,希望对你有帮助.我暂且按照目前的 Star 数量来排序. 本文由 SnailClimb 整理,如需转载请联系作 ...

  3. 深圳--博雅互动 Android面试打酱油归来

    公司在TCL工业园E4,坐地到西丽站,那边在修路,不好走.B796公交站台在A出口的反方向,还要顺着施工的屏障打个弯,在西丽法院1上车.公司那边比较偏了,附近只有两趟公交.办公地点在10楼,出电梯就可 ...

  4. IOS培训还值得么

    文章结构 1培训机构 各方面的评价 培训安排 收获 2 市场 就业 是否饱和 3 姿势 做好的事情 IOS这几年在IT界一直是热门的讨论话题,之前看着拉钩出品的北上广高薪岗位的人员技术流动也主要指向这 ...

  5. 我是如何自学 Python 的

    不少初学 Python 或者准备学习 Python 的小伙伴问我如何学习 Python.今天就说说我当时是怎么学习的. 缘起 我大学专业是电气工程,毕业后做的是自动化方面的工作.对于高级语言编程基本是 ...

  6. 小白数据分析——Python职位全链路分析

    最近在做Python职位分析的项目,做这件事的背景是因为接触Python这么久,还没有对Python职位有一个全貌的了解.所以想通过本次分析了解Python相关的职位有哪些.在不同城市的需求量有何差异 ...

  7. 阶段总结-Java基础-超进阶

    Gitee项目地址:https://gitee.com/zc10010/java_interview_guide/tree/master/知识点话术 项目叫话术,但是我觉得作为知识点学习是挺不错的. ...

  8. 【poj2151】 Check the difficulty of problems

    http://poj.org/problem?id=2151 (题目链接) 题意 T支队伍,一共M道题,第i支队伍解出第j道题的概率为p[i][j].问每支队伍至少解出1道题并且解题最多的的队伍至少解 ...

  9. XidianOJ 1020 ACMer去刷题吧

    题目描述 刷题是每个ACMer必由之路,已知某oj上有n个题目,第i个题目小X能做对的概率为Pi(0<=Pi<=1,1<=i<=n) 求小X至少做对k道题的概率 输入 第一行输 ...

随机推荐

  1. PostgresSql开放局域网访问

    1) 确认已经退掉所有的MASF终端和MSF GUI,然后打开PostgresSQL的启动文件在文件POSTGRESQL_START参数后面添加-h 0.0.0.0,让PostgreSQL启动时绑定到 ...

  2. [SAP ABAP开发技术总结]搜索帮助Search Help (F4)

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  3. JavaScript Replace 多个字符

    <html> <head> <title></title> <script language="javascript"> ...

  4. python_way day21 Django文件上传Form方式提交,原生Ajax提交字符处啊,Django文件上传之原生Ajax方式、jQuery Ajax方式、iframe方式,Django验证码,抽屉示例,

    python_way day21 1.Django文件上传至Form方式 2.原生Ajax文件上传提交表单 使用原生Ajax好处:不依赖jquery,在发送一个很小的文件或者字符串的时候就可以用原生A ...

  5. OnClientClick的用法

    摘自:http://blog.csdn.net/coolpig86/article/details/5439560 OnClientClick用于执行客户端脚本.当我们单击一个按钮时,最先执行的是On ...

  6. SpringMVC后缀

    <!-- 在这里,使用*.html为后缀的URL都能被baobaotao Servlet截获,进而转由SpringMVC框架进行处理.在 Struts框架中,一般将URL后缀配置为*.do:在w ...

  7. Jquery 移除 html中绑定的onClick事件

    HTML绑定示例: <button class="edit" onClick="showTurnEdit(this)">编辑</button& ...

  8. [转载] 每周推荐阅读 BFQ:实现IO的隔离共享与高吞吐访问

    磁盘IO和网络IO隔离与共享是混部应用中基本需求,从早些年的BVC到现在的Matrix,以及Galaxy,或者未来的BS/Mint混部都遇到类似的问题:由于无法有效实现IO级的隔离(包括吞吐隔离.延时 ...

  9. Eclipse中配置Tomcat服务器

    在首先外部安装好tomcat,然后在eclipse配置Tomcat服务器: 选择要配置的tomcat版本: 选择tomcat的安装的路径,选择你安装的JRE: 到此tomcat服务器就算是配置好了,接 ...

  10. Java数组实现五子棋功能

    package ch4; import java.io.*; /** * Created by Jiqing on 2016/11/9. */ public class Gobang { // 定义棋 ...