回溯法 全排列思路(自溜用)

这个文章大部分内容来自代码随想录的文章,我自己补充一些内容,把递归过程全部列举一遍,写的更详细一点,自己复习用。
题目:给定⼀个 没有重复数字的序列,返回其所有可能的全排列。
⽰例:
输⼊: [1,2,3]
输出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
回溯法通用模板:
一般是两个全局变量
vector<string>path;
vector<vector<string>>result;

void backtracking (参数) 组合问题一般要传startIndex,排列问题用不上startIndex一般不传
{

	if(递归终止条件)
	{
		result.push_back(path) 即存放结果
		return;
	}
		for (遍历本层内容)
		{
			//正式执行题目相关要求,处理节点
            path.push_back(参数)  一般在此时会写入path

			backtracking(参数)

			回溯,撤销此前的所有操作
            最起码是有一个path.pop_back()
		}
}

然后是主函数调用backtracking就行,主函数一般没有内容,只负责调用和传初始参数

下面聚焦到此题上:

 排列问题不用startIndex,但要多用一个used[]数组(图中橘色内容)保存数字是否使用过的信息。

当收集元素的数组 path 的⼤⼩达到和 nums 数组⼀样⼤的时候,说明找到了⼀个全排列,也
表⽰到达了叶⼦节点。
因为排列问题,每次都要从头开始搜索,例如元素 1 [1,2] 中已经使⽤过了,但是在 [2,1]
还要再使⽤⼀次 1 used 数组,其实就是记录此时 path ⾥都有哪些元素使⽤了,⼀个排列⾥⼀个元素只能使
⽤⼀次
全代码如下:
class Solution {
public:
         vector<vector<int>> result;
         vector<int> path;

    vector<vector<int>> permute(vector<int>& nums) {
            vector<bool> used(nums.size(), false);
            backtracking(nums, used);
            return result;
    }
    
    void backtracking (vector<int>& nums, vector<bool>& used){
             if(path.size()==nums.size())
             {
                 result.push_back(path);
                 return ;
             }
             for(int i=0;i<nums.size();i++)
             {
                 if(used[i]==true)continue;
                 used[i] = true;
                path.push_back(nums[i]);
                 backtracking(nums, used);
                 path.pop_back();
                used[i] = false;
             }
         }

};

之前学的过程中不知道哪里没想通,感觉排列问题比组合问题难理解,用startIndex隔开每一层递归的内容还好理解,这里老是没想明白,把整个过程打印出来捋一捋最后才想明白了。画一个图展示一下递归过程,下一次就不用想半天了,对着图和代码一起看就容易理清过程了。

结果集那里已经不是递归阶段负责的,到结果集那一步已经符合递归推出条件了。以{1,2,3}为例,可以在上面的代码里加上一段打印的代码看看过程。

   ...........
                path.push_back(nums[i]);
                backtracking(nums, used);
			for (int i = 0; i < path.size(); i++)
			{
				cout << path[i] << " ";
			}
			cout << endl;
   ...........
             

几张图结合着看就方便构思出整个过程,有助于理解回溯的思想。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值