在我做LintCode上面算法题目的时候,发现深度优先搜索算法是一个实用性非常强的算法,它帮助我解决了很多题目。下面我就来谈一下我对这个算法的理解和应用。
我觉得百度百科上面对于这个算法的解释还比较详细:
定义:
深度优先搜索算法(Depth-First-Search),是搜索算法的一种。是沿着树的深度遍历树的节点,尽可能深的搜索树的分支。当节点v的所有边都己被探寻过,
搜索将回溯到发现节点v的那条边的起始节点。这一过程一直进行到已发现从源节点可达的所有节点为止。如果还存在未被发现的节点,则选择其中一个作为源节
点并重复以上过程,整个进程反复进行直到所有节点都被访问为止。属于盲目搜索。
方法步骤
假设初始状态是图中所有顶点都未被访问,则深度优先搜索方法的步骤是:
1)选取图中某一顶点Vi为出发点,访问并标记该顶点;
2)以Vi为当前顶点,依次搜索Vi的每个邻接点Vj,若Vj未被访问过,则访问和标记邻接点Vj,若Vj已被访问过,则搜索Vi的下一个邻接点;
3)以Vj为当前顶点,重复步骤2),直到图中和Vi有路径相通的顶点都被访问为止;
4)若图中尚有顶点未被访问过(非连通的情况下),则可任取图中的一个未被访问的顶点作为出发点,重复上述过程,直至图中所有顶点都被访问。
举例说明:
首先,我们来想象一只老鼠,在一座不见天日的迷宫内,老鼠在入口处进去,要从出口出来。那老鼠会怎么走?当然是这样的:老鼠如果遇到直路,就一直往前走,
如果遇到分叉路口,就任意选择其中的一个继续往下走,如果遇到死胡同,就退回到最近的一个分叉路口,选择另一条道路再走下去,如果遇到了出口,
老鼠的旅途就算结束了。深度优先搜索法的基本原则就是这样:按照某种条件往前试探搜索,如果前进中遭到失败(正如老鼠遇到死胡同),则退回头另选通路继续
搜索,直到找到条件的目标为止。
好了,引用了这么多内容,只是因为我觉得这些东西也正好是我的理解,总结的也比较好,但是写一篇博客,总要有自己的干货,下面,我就结合我自己用到的来谈下自己的理解:
我解题的具体程序和思路就不说了,有兴趣的同学可以点击上面链接查看原博客。下面我只从深度优先搜索的角度分析我的程序。
private boolean canCross(int[] stones, int currentLocation, int lastStep) { //注释0
if (currentLocation == stones.length - 1) return true; //注释1
int next = 0;
if ((next = findNextLocation(stones, currentLocation, lastStep + 1)) != -1 //注释2
&& canCross(stones, next, lastStep + 1)) //注释3
return true; //注释4
if ((next = findNextLocation(stones, currentLocation, lastStep)) != -1
&& canCross(stones, next, lastStep))
return true;
if ((next = findNextLocation(stones, currentLocation, lastStep - 1)) != -1
&& canCross(stones, next, lastStep - 1))
return true;
return false; //注释5
}
A。首先,深度优先搜索算法的一大特色就是使用递归,注释0就是这个递归方法的主题,这个方法有三个参数,分别是保存有所有石头位置的stones数组,当前的位置currentLocation,从上一步跨到这一步我的步距是多少,这三个缺一不可,因为我们需要由当前位置出发,结合上一步的步距来确定下一步的三种跨度方案(如果青蛙最后一个跳 k 个单位,那么它下一次只能跳 k – 1 ,k 或者 k + 1 个单位)。
B。注释1的代码说明青蛙已经跳到了最后一块石头上面,说明这个递归过程已经成功了,结束了。
C。由代码可知,每当青蛙跳到一块石头上面,青蛙就有三种选择,然后青蛙会逐个地对这三种选择进行尝试,如果第一种选择不行,就尝试第二种选择,第二种不行就尝试第三种,如果三种子方法全部不行,我就通知上一个调用我的方法,告诉他我这儿三种选择都失败了,然后上一级的节点方法就会调用我的兄弟方法,然后兄弟方法就会测试它的三个子方法,。。。依次类推。。