题目:全排列
核心在于“交换”的步骤
首先从第一个元素开始,既然首元素已经确定了,之后就是递归地对后面的元素进行全排列
本质上就是让所有元素都当一次第一个元素,再让此时的第一个元素之后的所有元素当一次第二个元素…..以此类推,从前往后每个位置分别有n、n-1、n-2个种选择,也就是n!种排列方式
1vector<vector<int>> permute(vector<int>& nums)
2{
3 vector<vector<int>> res;
4 res.reserve(factorial(nums.size()));
5
6 backTrack(nums, res, 0);
7 return res;
8}
9
10void backTrack(vector<int>& nums, vector<vector<int>>& res, int first)
11{
12 if(first == nums.size())
13 res.push_back(nums);
14
15 for(int i = first; i < nums.size(); i++)
16 {
17 std::swap(nums[first], nums[i]);
18 backTrack(nums, res, first + 1);
19 std::swap(nums[first], nums[i]);
20 }
21}
22
23size_t factorial(size_t sz)
24{
25 size_t res;
26 for(int i = 0; i < sz; i++) res *= i;
27 return res;
28}
补充解法:used 数组回溯
1class Solution
2{
3public:
4 std::vector<vector<int>> res;
5 std::vector<int> path;
6 void backTrack(vector<int>& nums, vector<bool> used)
7 {
8 // 终止条件
9 if(path.size() == nums.size())
10 {
11 res.push_back(path);
12 return;
13 }
14
15 for(int i = 0; i < nums.size(); i++)
16 {
17 // 如果当前元素已经被使用过了
18 // 就直接跳过它
19 if(used[i])
20 continue;
21
22 // 将当前元素标记为“已使用”
23 used[i] = true;
24 path.push_back(nums[i]);
25 // 对下一个元素进行操作
26 backTrack(nums, used);
27 // 撤销所有操作
28 path.pop_back();
29 used[i] = false;
30 }
31 }
32
33 vector<vector<int>> permute(vector<int>& nums)
34 {
35 // 用来标记已使用的元素
36 std::vector<bool> used(nums.size(), false);
37 backTrack(nums, used);
38 return res;
39 }
40};
来源:语雀原笔记