zoukankan      html  css  js  c++  java
  • 深度优先搜索(Depth-First-Search)精髓

    引例:迷宫问题 
    首先我们来想象一只老鼠,在一座不见天日的迷宫内,老鼠在入口处进去,要从出口出来。那老鼠会怎么走?当然可以是这样的:老鼠如果遇到直路,就一直往前走,如果遇到分叉路口,就任意选择其中的一条继续往下走,如果遇到死胡同,就退回到最近的一个分叉路口,选择另一条道路再走下去,如果遇到了出口,老鼠的旅途就算成功结束了。 
     
    深度优先搜索的基本原则就是这样:按照某种条件往前试探搜索,如果前进中遭到失败(正如老鼠遇到死胡同)则退回头另选通路继续搜索,直到找到满足条件的目标为止。  
    递归程序设计 
    然而要实现这样的算法,我们需要用到编程的一大利器---递归。当一个函数直接或者间接的调用了自己本身的时候,则发生了递归。 
    讲一个更具体的例子:从前有座山,山里有座庙,庙里有个老和尚,老和尚在讲故事,讲什么呢?讲:从前有座山,山里有座庙,庙里有个老和尚,老和尚在讲故事,讲什么呢?讲:从前有座山,山里有座庙,庙里有个老和尚,老和尚在讲故事,讲什么呢?讲:„„„„。好家伙,这样讲到世界末日还讲不玩,老和尚讲的故事实际上就是前面的故事情节,这样不断地调用程序本身,就形成了递归。万一这个故事中的某一个老和尚看这个故事不顺眼,就把他要讲的故事换成:“你有完没完啊!”,这样,整个故事也就嘎然而止了。

    我们编程就要注意这一点,在适当的时候,就必须要有一个这样的和尚挺身而出,把整个故事给停下来,或者说他不再往深一层次搜索,要不,我们的递归就会因计算机栈空间大小的限制而溢出,称为stack overflow。  
    递归的经典实例: 

    int factorial(int n) { 
       if (n == 0//基线条件(base case)    
        { 
          return 1;    
        } else
        { 
          return n * factorial(n - 1);    //将问题规模逐渐缩小,或者说转化为更小                              更简单的子问题      
        } 
    }                                                        

    引入DFS 水仙花数: 
    一个三位数abc如果满足abc = a^3 + b^3 + c^3 那么就把

    这个数叫做水仙花数,写一个程序,求出所有的水仙花数。  
    广义水仙花数: 
    如果一个N位数所有数码的N次方的和加起来等于这个数字本身,我们把这样的数叫做广义水仙花数,容易看出来水仙花数是N = 3的广义水仙花数现在,我们的任务是,输入一个m (m < 7) ,让你求出所有满足N = m的广义水仙花数。 3 (153 370 371 407) 5 (54748 92727 93084) 
    方法:数据规模很小,可以直接枚举所有情况,然后判断是否满足条件。 难点:循环层数不确定  
    于是我们现在的问题是,怎么实现这个m重循环?

    答案是:递归。  
    m重循环的实现:

    void dfs(int deep){
          if (deep > m) 
         {   //check answer 
         } 
         else if (deep <= m)
          {
               for (i = 1; i <= n; i++)    
                    dfs(deep + 1);  
            } 
    }      

    没错,这个就是深度优先搜索(Depth-First-Search),那么它为什么叫DFS呢?这就是我下面要讲的:  
    1、搜索树就是,搜索过程中所形成的树形结构。(图) 
    2、很容易发现,DFS我们在计算那个问题的时候,总是尽量往深里走,也就是说 深度比广度 优先,所以这种方法叫做深度优先搜索。 
    3、同样,如果我们一层一层搜索,这样,它的广度先得到了扩展,就叫做广度优先搜索(Breadth-First-Search, BFS)。  
    深度优先搜索解决问题的框架

    void dfs(int deep, State curState) {
          if (deep > Max) //深度达到极限
          {   
                if (curState == target) //找到目标
               {    //... 
               } 
          } else{
                      for (i = 1; i <= totalExpandMethod; i++) 
                     {   
                          dfs(deep 1, expandMethod(curState, i));  
                     } 
          }
    }                                                                          
  • 相关阅读:
    leetcode231 2的幂 leetcode342 4的幂 leetcode326 3的幂
    leetcode300. Longest Increasing Subsequence 最长递增子序列 、674. Longest Continuous Increasing Subsequence
    leetcode64. Minimum Path Sum
    leetcode 20 括号匹配
    算法题待做
    leetcode 121. Best Time to Buy and Sell Stock 、122.Best Time to Buy and Sell Stock II 、309. Best Time to Buy and Sell Stock with Cooldown 、714. Best Time to Buy and Sell Stock with Transaction Fee
    rand7生成rand10,rand1生成rand6,rand2生成rand5(包含了rand2生成rand3)
    依图
    leetcode 1.Two Sum 、167. Two Sum II
    从分类,排序,top-k多个方面对推荐算法稳定性的评价
  • 原文地址:https://www.cnblogs.com/li303491/p/4108991.html
Copyright © 2011-2022 走看看