leetcode:46. 全排列 - 力扣(LeetCode)
题目
给定一个 没有重复 数字的序列,返回其所有可能的全排列。
示例:
- 输入: [1,2,3]
- 输出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ]
思路
没有重复!那么本题不需要startIndex。
排列是有序的!也就是说[1,2] 和 [2,1] 是两个集合
但是需要used数组,因为在一个树枝上面元素不可以重复使用。
本题抽象成下面的这棵树:
回溯三部曲
(1)全局变量:result,path。输入参数:nums,used。
(2)收集叶子节点,就是path.size==nums.size。
(3)排列我们需要取所有的元素,也就是说要搜索集合{1,2,3}的所有元素。
比如先取2,之后1、3都要取,说明for循环i从0开始,used数组是用来告诉我们2已经取了。
代码如下:
#include <iostream>
#include <vector>
using namespace std;
class Solution
{
private:
vector<vector<int>> result;
vector<int> path;
void backtracking(vector<int> &nums, vector<bool> &used)
{
// 当path的大小等于nums的大小时,找到了一个完整的排列
if (path.size() == nums.size())
{
result.push_back(path);
return;
}
// 遍历nums中的每个元素
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;
}
}
public:
vector<vector<int>> permute(vector<int> &nums)
{
vector<bool> used(nums.size(), false);
backtracking(nums, used);
return result;
}
};
总结
排列问题跟组合问题的区别:
(1)排列从0开始搜索,不需要startIndex。
(2)这里用了used数组,但是我们却没有sort,因为这里的used数组并不是用来处理树层重复的,而是为了记录同一树枝上已经使用过的元素。