回溯算法初涉

什么是回溯算法?

回溯算法也是深度搜索算法(DFS),也是递归。

回溯算法是最基本的暴力解决算法,可以很好的解决大多数问题,由此我们需要掌握它。

 

递归有两点要素:

1. 递归边界。

2. 递归的逻辑——递归"公式"。

递归边界即是需要我们自己寻找的程序出口,这是递归的终点,它将返回子问题的解。

递归公式则理解为对于问题的合理分解。即将一个大问题,合理的将之简化为子问题。也就是说将一个复杂的系统通过合理的方式拆解为单位动作。我们需要研究的也就是如何合理分解

 

下面将给出一个递归函数框架(并不是固定不变的,会根据问题的变化而改动),可以进行适当的理解。

返回类型 dfs(形参1,形参2,形参3,...,形参n){
    if (递归边界){
        return 子问题的解
    }

    通过合理的方式拆解问题
    
}

 

下面举几个例子。

 

71.子集

问题:

给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。

说明:解集不能包含重复的子集。

示例:

输入: nums = [1,2,3]
输出:
[
  [3],
  [1],
  [2],
  [1,2,3],
  [1,3],
  [2,3],
  [1,2],
  []
]

思路:

这道题要我们返回数组所有的子集(不包含重复子集)。我们将之拆分:

1. 将输出分为三部分,分别输入1位,2位,3位,...,n位。

2. 通过循环,将数组中的后面的数字逐个推进栈中。

3. 建立递归边界,即为判断容器 vector 中的数字达到 k 值没有。

 

程序:

class Solution {
public:
    
    vector<vector<int>> res;
    vector<int> tmpv;
    
    vector<vector<int>> subsets(vector<int>& nums) {
        for (int k=0;k<=nums.size();k++)    // 将输出分为n部分
            dfs(nums,0,k);
        
        return res;
    }
    
    void dfs(vector<int> num, int i,int k){
        if (i == k)    // 判断是否与输出数字量相同
            res.push_back(tmpv);
        
        for (int j=i;j<k;j++){    // 循环
            tmpv.push_back(num[j]);  // 推入栈中
            dfs(num,j+1,k);    // 递归,加入下一个数
            tmpv.pop_back();    // 返回原来的状态
        }
    }
};

 

46. 全排列

题目:

给定一个没有重复数字的序列,返回其所有可能的全排列。

示例:

输入: [1,2,3]
输出:
[
  [1,2,3],
  [1,3,2],
  [2,1,3],
  [2,3,1],
  [3,1,2],
  [3,2,1]
]

 

思路:

题目让我们返回给定序列所有的排列组合。

由此我们开始拆解问题,将之分成多个子问题:即两个交换元素(当只有两个元素时,交换一次即可。)。

从第一个元素开始作为交换点,不断与后续元素交换,得到新的序列。返回状态,再从第二个元素开始。。。

程序:

 

class Solution {
public:
    
    vector<vector<int>> res;
    vector<int> tmpv;
    vector<vector<int>> permute(vector<int>& nums) {
        dfs(nums,0);
        return res;
    }
    
    void dfs(vector<int> &nums,int i){
        if (i == nums.size())    //
            res.push_back(nums);
        
        for (int j=i;j<nums.size();j++){
            swap(nums[j],nums[i]);
            dfs(nums,i+1);
            swap(nums[j],nums[i]);
        }
    }
};

 

 

 


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值