首先,本人声明一下,这篇博客是看了其他人写的博客之后,对这个面试题十分感兴趣,所以才想分享一下。
在明白这个面试题的时候,先通过一个简单的迷宫问题,明白一下几个问题:
什么是“搜索”?什么是“剪枝”?什么是“回溯”?
“搜索”:
每个点都可以按照右下左上的方向进行尝试,如果是“墙壁”,就换一个方向,如果可以走,就往前走到下一点,然后再接着尝试。
“剪枝”:
之前走过的路,就不在往那边走了,因为回去的话,下一步还要回来。不在搜索一些明显不对的地方,剪掉没用的分支,提高效率。
“回溯”:
如果我们正在往前搜索,前面没有路的时候,我们就需要返回来,找到之前有可能出现岔路口的地方,再去下一个方向搜索
明白以上问题以后,来看这个类似华容道的问题:
空格可以和上下左右的数字进行交换,你可以认为空格在移动。如果移动成:
如图所示,空格不能往右走,被墙挡住了,不过可以往上、下、左走,这个状态,空格就有上、下、左三个方向可以进行搜索,空格往下走一步,这时候可以往左和往上,往上的话又回到原来状态了,所以应该“剪枝”,那么什么时候应该进行“回溯”呢?就是在当前状态无论哪个方向都行不通的时候,但是这时候的“回溯”,不是像迷宫问题中走不通的时候才用,二十前面的路是之前走过的,也不应该再往前走了,应该“回溯”,像这个华容道,如果是按照右上方的方向移动,确实可以无线进行。但是转到第三圈的时候,会发现和刚开始的状态一直,所以不应该再继续转下去了,所以这个时候应该考虑“回溯”。
那么明白搜索过程后,应该怎么写代码实现“回溯”算法呢?
看到这里我们会想到用栈去操作,但是这个问题直接用栈的话,编码比较难,所以我们可以使用递归来实现这个搜索过程。意思是把搜索定义成一个函数,然后里面又调用搜索这个函数自身,当搜索到“穷途末路”时,搜索函数返回,会自动会到上一层的调用中,从而完成回溯。
那么什么时候判断九宫格能否达到游戏胜利的状态呢?
如果每条路都被堵住,回溯算法就会回溯到起点,如果回溯到起点状态,还没有找到游戏胜利的话,就是不能达到胜利状态。
正确的移动步骤应该如何记录呢?