深度优先搜索小结
有一类问题,是逐步生成结果的形式,有明确的递推形式,边界非常明确,比较容易用迭代形式实现,用递归也有较为明确的层数和宽度 ,这类问题,能用迭代就用迭代,用递归很大可能会超时,当然封闭形式的解最好。例如:走楼梯,走方格,硬币表示,括号组合,子集,全排列。
有另外一类问题,解的空间很大(往往是阶乘级别的),要在所有可能性中找到答案,只能进行试探。尝试往前走一步,走不通再退回来,这就是DFS+回溯+剪枝。对这类问题优化,使用剪枝,越早剪越好,但这很难。例如:素数环。
关于深度优先搜索算法的几个注意的地方,首先先要确定题目适不适合用DFS去求解,这种解法适用于解的空间很大的情况。确定使用DFS过后,做这类题目基本都要遵循由简到繁的步骤,不要想着一开始就这样那样划分任务,这样是不行的。先举几个例子,由简到深,然后模拟调用DFS的过程,看能不能解决这道题目。确定了使用DFS算法之后最核心的就是如何处理平行状态,有的题目可能涉及两个平行状态,有的题目可能涉及多个平行状态,像数独游戏这道题目就存在多个平行的状态。
第二、关于回溯的问题,在DFS过程中,可能最重要的就是回溯了吧。有的代码可能没有明确的写出回溯的代码,有两种可能,一是循环调用DFS,当一次循环结束,自动回溯到下一层循环再调用DFS。二是可能有些题目需要写回溯,而有些题目不需要写回溯,还有些题目可能需要回溯也可,不需要写回溯也可。但是是否需要写回溯需要看具体的情况来决定。假如退回来的时候,退回来的结果对下一次试探有影响的话,那么就需要回溯,反之则就不需要回溯。
第三、在调用DFS的过程中可能涉及要记录其中的过程,其中我们经常使用到List,HashMap,StringBuilder,HashSet,数组这些数据结构来记录其中动态变化的情况。
最后,出口的处理以及check()函数的编写要注意细节。还有关于DFS方法中参数的地方,可以适当地增加参数,这样能更方便处理。还要多看看前面博客记录的题,以达到模式匹配的效果,这样一看到新的题目就知道是以前学习过的题目换汤不换药而已,而不是无从下手的感觉。
本文来自博客园,作者:|旧市拾荒|,转载请注明原文链接:https://www.cnblogs.com/xiaoyh/p/10351435.html