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

  

    interface IPath
{
/// <summary>
/// 增加某条地铁线路
/// </summary>
/// <param name="lineNo">地铁线号</param>
/// <param name="stationNum">站点数目</param>
/// <param name="stationArray">地铁线站台号数组</param>
void AddLine(int lineNo, int stationNum, int[] stationArray); /// <summary>
/// 计算从超点到终点的最短路线长度
/// </summary>
/// <param name="srcStation">起点站</param>
/// <param name="desStation">终点站</param>
/// <returns>起点站到终点站最短线长度</returns>
int CalcMinPathLen(int srcStation, int desStation); /// <summary>
/// 输出从起点到终点的最短路线
/// </summary>
/// <param name="srcStation">起点</param>
/// <param name="desStation">终点</param>
/// <param name="pathNum">条数</param>
/// <param name="pathLen">长度</param>
/// <param name="pathes">结果路线集合</param>
/// <returns>0成功 -1出错</returns>
int SearchMinPaths(int srcStation, int desStation, out int pathNum, out int pathLen, out int[][] pathes); /// <summary>
/// 最优路线
/// </summary>
/// <param name="srcStation">起点</param>
/// <param name="desStation">终点</param>
/// <param name="pathNum">条数</param>
/// <param name="pathLen">长度</param>
/// <param name="pathes">结果路线集合</param>
/// <returns>0成功 -1出错</returns>
int SearchBestPathes(int srcStation, int desStation, out int pathNum, out int pathLen, out int[][] pathes); }

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

int CalcMinPathLen(int srcStation, int desStation);

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

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

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

两个方法代码如下

    public class MetroPath : IPath
{
private readonly List<Tuple<int, int, int[]>> pathes;
private int stationCount = ; private List<int> minStations; public MetroPath()
{
pathes = new List<Tuple<int, int, int[]>>();
minStations = new List<int>();
} public void AddLine(int lineNo, int stationNum, int[] stationArray)
{
if (stationNum < || stationArray == null || stationArray.Length != stationNum)
Console.WriteLine("站点数目不对");
else
pathes.Add(new Tuple<int, int, int[]>(lineNo, stationNum, stationArray));
} public int CalcMinPathLen(int srcStation, int desStation)
{
//用迪杰斯特拉算法计算
Dictionary<int, int> stationLens = new Dictionary<int, int>(); IEnumerable<int> ct = pathes[].Item3;
//得到所有站数
foreach (var a in pathes)
{
ct = ct.Union(a.Item3);
}
stationCount = ct.Distinct().Count(); try
{
stationLens.Add(srcStation, );//初始 while (stationLens.Count < stationCount)
{
stationLens = FindMinStation(stationLens, srcStation);
} //下一题用
minStations = stationLens.Select(x => x.Key).ToList(); //找出起点到终点最短长度
return stationLens[desStation];
}
catch
{
return -; //出错
}
} //找出余下站点中最短的站点及起点到它的长度
private Dictionary<int, int> FindMinStation(Dictionary<int, int> stations, int srcStation)
{
Dictionary<int, int> lens = new Dictionary<int, int>(); foreach (var p in pathes)
{
foreach (var station in p.Item3)
{
if (!stations.ContainsKey(station))
{
//计算最小值
var minlen = ReachLen(stations, srcStation, station);
if (minlen > && !lens.ContainsKey(station))
lens.Add(station, minlen);
}
}
} //找出lens中最小的(可以多个)加入集合
int min = lens.Min(v => v.Value); return stations.Union(lens.Where(x => x.Value == min)).ToDictionary(k => k.Key, v => v.Value);
} //是否是可达的 -1为不可达
private int ReachLen(Dictionary<int, int> stations, int srcStatoin, int station)
{
List<int> reachStations = new List<int>();
foreach (var p in pathes)
{
for (int i = ; i < p.Item3.Length; i++)
{
if (p.Item3[i] == station)
{
if (i - >= && !reachStations.Contains(p.Item3[i - ]))
reachStations.Add(p.Item3[i - ]);
if (i + < p.Item3.Length && !reachStations.Contains(p.Item3[i + ]))
reachStations.Add(p.Item3[i + ]);
}
}
} var q = stations.Where(v => reachStations.Contains(v.Key));
//相邻点不在集合里面
if (q == null || q.Count() <= )
return -;
else
{
//找出q中最小的值
return q.OrderByDescending(v => v.Value).First().Value + ;
} } public int SearchMinPaths(int srcStation, int desStation, out int pathNum, out int pathLen, out int[][] pathes)
{
pathNum = ;
pathLen = ;
pathes = null; try
{
pathLen = CalcMinPathLen(srcStation, desStation); List<int[]> result = new List<int[]>(); Stack<int> sk1 = new Stack<int>();
List<Tuple<int, int>> list = new List<Tuple<int, int>>(); sk1.Push(srcStation);
minStations.Remove(srcStation); int ct = ;
int deepth = ;
while (deepth > )
{
bool flag = false;
foreach (var x in minStations)
{
list.RemoveAll(v => v.Item1 > deepth); if (ExistsRalation(sk1.Peek(), x) && !sk1.Contains(x) && list.Where(v => v.Item2 == x).Count() <= )
{
sk1.Push(x);
deepth++;
flag = true;
break;
}
} //
if (sk1.Peek() == desStation)
{
//一条完整的路线
result.Add(sk1.Reverse().ToArray());
deepth--;
list.Add(new Tuple<int, int>(deepth, sk1.Pop()));
ct++;
}
//没有找到
if (!flag)
{
deepth--;
list.Add(new Tuple<int, int>(deepth, sk1.Pop()));
}
} pathNum = ct;
pathes = result.ToArray();
return ;
}
catch
{
return -;
} } private bool ExistsRalation(int a, int b)
{
if (a == b)
return false; foreach (var p in pathes.Where(x => x.Item3.Contains(a) && x.Item3.Contains(b)))
{
for (int i = ; i < p.Item3.Length; i++)
{
if (p.Item3[i] == a)
{
if (i - >= && p.Item3[i - ] == b)
return true;
if (i + < p.Item3.Length && p.Item3[i + ] == b)
return true;
}
}
}
return false; } public int SearchBestPathes(int srcStation, int desStation, out int pathNum, out int pathLen, out int[][] pathes)
{
throw new NotImplementedException();
}
}

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

最后是调用代码和结果

            //测试
IPath mp = new MetroPath();
mp.AddLine(, , new int[] { , , , , });
mp.AddLine(, , new int[] { , , , , });
mp.AddLine(, , new int[] { , , });
mp.AddLine(, , new int[] { , }); var min = mp.CalcMinPathLen(, );
Console.WriteLine("从1到11最短路径长度为:{0}", min); int pathNum = ;
int pathLen = ;
int[][] pathes = null;
var re = mp.SearchMinPaths(, , out pathNum, out pathLen, out pathes); Console.WriteLine("从1到11最短路径条数为{0},分别是", pathNum);
foreach (var x in pathes)
{
Console.Write("\n{");
foreach (var i in x)
{
Console.Write("{0},", i);
}
Console.Write("}\n");
} Console.ReadLine();

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

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

        /// <summary>
/// 深度优先
/// </summary>
static void DFS(int[,] a, int n)
{
Stack<int> sk1 = new Stack<int>();
Stack<int> sk2 = new Stack<int>();
sk1.Push();
Console.WriteLine();
int x = ;//访问点标记 int ct = ;//访问节点数
while (ct < n)
{
int i = ;
bool f = false;
for (i = ; i < n; i++)
{
if (a[x, i] != && !sk2.Contains(i))
{
sk1.Push(i);
Console.WriteLine(i); ct++;
x = i; f = true;
break;
}
}
if (!f)
{
//没有找到返回
sk2.Push(sk1.Pop());
x = sk1.Peek();
} }
}

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

            int[,] a = {
{,,,,}
,{,,,,}
,{,,,,}
,{,,,,}
,{,,,,}
}; Console.WriteLine("DFS:");
DFS(a, );
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. CUBRID学习笔记 25 数据类型2

    ---恢复内容开始--- 6枚举类型 语法 <enum_type> : ENUM '(' <char_string_literal_list> ')' <char_str ...

  2. hdu 4946 Just a Joke(数学+物理)

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=4969 Just a Joke Time Limit: 2000/1000 MS (Java/Others) ...

  3. hdu 2112 (最短路+map)

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=2112 HDU Today Time Limit: 15000/5000 MS (Java/Others)  ...

  4. 【CC评网】2013.第39周 漂亮的作息表

    作息表 网上看到一份夏令时的作息表,让人羡慕不已: 5:00 起床——迷糊5分钟,喝500ML白开水,坐马桶看Google reader 5:20 小区6KM(大约25min—30min)+100个俯 ...

  5. vim功能使用

    转自:http://blog.csdn.net/xiajun07061225/article/details/7039413 vi与vim vi编辑器是所有Unix及Linux系统下标准的编辑器,他就 ...

  6. HTTP协议(转自:小坦克博客)

    原文地址:http://www.cnblogs.com/TankXiao/archive/2012/02/13/2342672.html HTTP协议详解 当今web程序的开发技术真是百家争鸣,ASP ...

  7. js 监听监键盘动作(转)

    主要分四个部分 第一部分:浏览器的按键事件 第二部分:兼容浏览器 第三部分:代码实现和优化 第四部分:总结 第一部分:浏览器的按键事件 用js实现键盘记录,要关注浏览器的三种按键事件类型,即keydo ...

  8. 在.bashrc文件中定义函数

    在命令行上直接定义shell函数的明显缺点是当退出shell时,函数就消失了,对于复杂的函数来说,这可能会是个问题. 一个简单的方法就是每次启动新shell的时候都会自动加载所需要的函数. 最好的办法 ...

  9. iOS - Alamofire 网络请求

    前言 Alamofire 是 Swift 语言的 HTTP 网络开发工具包,相当于 Swift 实现 AFNetworking 版本.当然,AFNetworking 非常稳定,在 Mac OSX 与 ...

  10. poj2986A Triangle and a Circle&&poj3675Telescope(三角形剖分)

    链接 2986是3675的简化版,只有一个三角形. 这题主要在于求剖分后三角形与圆的相交面积,需要分情况讨论. 具体可以看此博客 http://hi.baidu.com/billdu/item/703 ...