回溯算法讲解--适用于leetcode绝大多数回溯题目

栏目: 编程工具 · 发布时间: 5年前

内容简介:什么是回溯算法?回溯法是一种系统说到底它是一种

什么是回溯算法?

回溯法是一种系统 搜索 问题 解空间 的方法。为了实现回溯,需要给问题定义一个 解空间

说到底它是一种 搜索算法 。只是这里的搜索是在一个叫做 解空间 的地方搜索。

而往往所谓的dfs,bfs都是在图或者树这种数据结构上的搜索。

根据定义来看,要实现回溯,需要两点 1搜索2解空间

先看什么是 解空间

就是形如数组的一个向量[a1,a2,....,an]。这个向量的每个元素都是问题的部分解,只有当这个数组的每一个元素都 填满 (得到全部解)的时候,才表明这个问题得到了解答。

再看 搜索

最简单的就是for循环,上面的向量有n个维度,因此就是n个for循环。

形如:

for(求a1位置上的解)
   for(求a2位置上的解)
      for(求a3位置上的解)
       ......
       ......
       for(求an位置上的解)

但是如果n是100?n是100000?那么如何回溯?

当然也可以写n个for循环,但是这样的程序会惨不忍睹。。。而且似乎10000个(不过往往回溯的时间复杂度太大,一般n不会这么大)for循环也很难写出来。。。

因此我们需要一种全新的书写回溯的方法。形如:

void backtrack(int i,int n,other parameters)
{
  if( i == n)
{
 //get one answer
record answer;
return;
}
//下面的意思是求解空间第i个位置上的下一个解
for(next ans in position i of solution space)
{
  backtrack(i+1,n,other parameters);
}
}

就是这么简单!!!

上面的模板适用于所有"解空间确定"的回溯法的问题!!!

上面的i代表解空间的第i个位置,往往从0开始,而n则代表解空间的大小。每一次的backtrack(i,n,other)调用,代表求 解空间 第i个位置上的解。而当i=n时,代表解空间上的所有位置的解都已经求出。

有了上述 模板 ,我们就解决了 搜索 的问题。

因此 几乎 所有回溯的问题的难度都在于如何定义 解空间

下面通过题目,带入模板,然后再看我的解答,来感知一下如何定义解空间。

全排列 https://segmentfault.com/a/11...

即对没有重复数字的数组a=[a1,a2,a3,...an]求全排列。

解空间定义为s=[s1,s2,s3,....sn]与数字长度相同。s的每一个元素s【i】(i >= 0&&i < n),都为数组a中的任意元素a【j】(j >= 0&&j < n),不过要保证任意的s【i】不相等。

这里唯一复杂的地方是需要用一个boolean【】数组来表明哪些数已经用过,这样才能保证任意的s【i】不相等。

因此我们看到,回溯本身是很简单的,单纯的模板套用,难的在于需要根据回溯条件来定义各种别的变量,以及最后结果的记录。

探测路径 https://leetcode-cn.com/probl... (这个下面给出ac 代码)

这个题很难,但是掌握了如何定义解空间之后再做这个题就会感觉是小儿科了。

这里的解空间s = [s1,s2,s3,....sn]中的每一个元素s【i】代表格子的坐标(x,y),因此从 逻辑上 来看,s应该是一个类类型的数组。不过,这个题求的是数目,而不是最后的确切路径,因此解空间在这里并没有记录。

java ac代码:

class Solution {
    int ans;
    public int uniquePathsIII(int[][] grid) {
        if(grid.length == 0)return 0;
        int num = 0;
        int x = 0,y = 0;
        for(int i = 0;i < grid.length;i++)
            for(int j = 0;j < grid[0].length;j++){
                if(grid[i][j] == 1||grid[i][j] == 0)num++;
                if(grid[i][j] == 1){x = i;y = j;}
            }
        backtrack(0,num,x,y,grid,new boolean[grid.length][grid[0].length]);
        return ans;
    }
    
    void backtrack(int i,int n,int x,int y,int[][]grid,boolean[][]flag)
    {
        if(!(x >= 0 && x < grid.length && y >= 0 && y < grid[0].length)||flag[x][y]||grid[x][y] == -1)
            return;
        if(i == n && grid[x][y] == 2)
        {
            ans++;
            return;
        }
        flag[x][y] = true;
        backtrack(i+1,n,x+1,y,grid,flag);
        backtrack(i+1,n,x-1,y,grid,flag);
        backtrack(i+1,n,x,y+1,grid,flag);
        backtrack(i+1,n,x,y-1,grid,flag);
        flag[x][y] = false;
    }
}

上面这个题的解空间应该有N+1个才对,但是为了方便书写,我只求出前n个位置的解,然后保证最后一个位置是终点即可。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Hackers

Hackers

Steven Levy / O'Reilly Media / 2010-5-30 / USD 21.99

This 25th anniversary edition of Steven Levy's classic book traces the exploits of the computer revolution's original hackers -- those brilliant and eccentric nerds from the late 1950s through the ear......一起来看看 《Hackers》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具