回溯算法

今天刷leetcode的时候遇到了回溯算法的经典问题,生成n个括号的组成方式
这里就直接贴上代码了,顺便巩固一下回溯算法。

class Solution {
public:
    vector generateParenthesis(int n) {
        vector rev;
        append("",rev,n,n);
        return rev;
    }
    void append(string curstr,vector &rev,int nl,int nr)
    {
        if(nl == 0 && nr == 0)
            rev.push_back(curstr);
        if(nl0)
            append(curstr+'(',rev,nl-1,nr);
    }
};

这段代码的关键就在于append函数的迭代计算中,由此来形成枚举遍历的回溯的效果。

回溯算法简介

回溯法有通用解法的美称,对于很多问题,如迷宫等都有很好的效果。回溯算法实际上一个类似枚举的深度优先搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”返回(也就是递归返回),尝试别的路径。许多复杂的,规模较大的问题都可以使用回溯法,有“通用解题方法”的美称。回溯法说白了就是穷举法。回溯法一般用递归来解决。


作者:littlelufisher
来源:CSDN
原文:https://blog.csdn.net/sinat_27908213/article/details/80599460
版权声明:本文为博主原创文章,转载请附上博文链接!

这篇博文说的很好,并且有一些例题,可以借鉴一下。

下面写一点对于回溯算法的自己的见解:
回溯算法,在我的理解上算是一种十分优美的穷举方法,虽然它是穷举,但是不同于一般的暴力穷举,回溯算法在很大程度上节约了运算时间。在上文中有提到回溯算法的三个要素:选择,条件,结束。
现在从代码上来分析:

  if(nl == 0 && nr == 0)
            rev.push_back(curstr);
        if(nl0)
            append(curstr+'(',rev,nl-1,nr);

这里的if语句起到了选择的作用,这道题目比较简单,只有两种选择,可以把他看成二叉树的两个子树分支,而第一个if就起到了条件判断返回的作用,因为这里我用了引用,传出参数,所以不存在返回值。在这里curstr就是作为一个临时变量存储不完整的解以不断地走下去,而nl和nr =0就是结束的条件了。

递归函数的参数的选择,要遵循四个原则:
1、必须要有一个临时变量(可以就直接传递一个字面量或者常量进去)传递不完整的解,因为每一步选择后,暂时还没构成完整的解,这个时候这个选择的不完整解,也要想办法传递给递归函数。也就是,把每次递归的不同情况传递给递归调用的函数。
2、可以有一个全局变量,用来存储完整的每个解,一般是个集合容器(也不一定要有这样一个变量,因为每次符合结束条件,不完整解就是完整解了,直接打印即可)。
3、最重要的一点,一定要在参数设计中,可以得到结束条件。一个选择是可以传递一个量n,也许是数组的长度,也许是数量,等等。
4、要保证递归函数返回后,状态可以恢复到递归前,以此达到真正回溯。

作者:littlelufisher
来源:CSDN
原文:https://blog.csdn.net/sinat_27908213/article/details/80599460
版权声明:本文为博主原创文章,转载请附上博文链接!

你可能感兴趣的:(Leetcode反思)