剑指offer——回溯法总结

面试题12 13是接连的两道回溯法的题。

 

先上定义:

回溯法按深度优先策略搜索问题的解空间树。首先从根节点出发搜索解空间树,当算法搜索至解空间树的某一节点时,先利用剪枝函数判断该节点是否可行(即能得到问题的解)。如果不可行,则跳过对该节点为根的子树的搜索,逐层向其祖先节点回溯;否则,进入该子树,继续按深度优先策略搜索。

    回溯法的基本行为是搜索,搜索过程使用剪枝函数来为了避免无效的搜索。剪枝函数包括两类:1. 使用约束函数,剪去不满足约束条件的路径;2.使用限界函数,剪去不能得到最优解的路径。

 

回溯法说白了就是递归,递归法算法简洁且执行效率高,但是与之相应的就是递归法一般都很抽象,很难想。

 

回溯法的经验小结:

  1. 出口: 出口就是判定条件,一般放在代码第一行,这样执行到终止条件的递归函数可以优先判定,避免有一些条件,内容的更改。
  2. 递归函数的参数设置: 这个参数是随着每一次的递归操作而发生改变的。而回溯法很关键的一点就是:如果当前操作行不通,如何回溯到上一步操作。所以不要改变参数,如下不可

for index in range(nums):

Flag = conflict(queen_str, index)

# 如果当前位置的皇后是否与之前所有位置的皇后没有冲突,则执行下述代码

if Flag is False:

queen_str = queen_str+str(index)

back(queen_str )

 

如下可:

for index in range(nums):

Flag = conflict(queen_str, index)

# 如果当前位置的皇后是否与之前所有位置的皇后没有冲突,则执行下述代码

if Flag is False:

back(queen_str+str(index))

 

典型例题:

剑指offer上的面试题12:请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一格开始,每一步可以在矩阵中向左、右、上、下移动一格。如果一条路径经过了矩阵的某一格,那么该路径不能再次进入该格子。例如,在下面的3×4的矩阵中包含一条字符串“bfce”的路径(路径中的字母用加粗标出)。

 

[["a","b","c","e"],

["s","f","c","s"],

["a","d","e","e"]]

 

但矩阵中不包含字符串“abfb”的路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入这个格子。

算法设计很考究。

class Solution {

public:

    bool exist(vector<vector<char>>& board, string word) {

      auto s=word.begin();

  for(int i=0;i!=board.size();++i){

  for(int j=0;j!=board[i].size();++j){

  if(dfs(i,j,board,word,0)) return true;//找到起始位置开始迭代



  }

  }

  return false;

    }

     bool dfs(int i,int j,vector<vector<char>>& board,string word,int k){

  if(i<0||i>=board.size()||j<0||j>=board[0].size()||board[i][j]!=word[k])

  return false;   //判断句放前,false放在true前面,否则不对

            if(k==word.size()-1)return true; //唯一正确判定方式

  char tmp=board[i][j];

  board[i][j]='/'; //如果过了false判定,就说明可以递归,先更改值,再下面改回来

  bool res=dfs(i-1,j,board,word,k+1)||dfs(i+1,j,board,word,k+1)||dfs(i,j-          1,board,word,k+1)||dfs(i,j+1,board,word,k+1);

  board[i][j]=tmp;

  return res;

  }

};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值