文章目录
- 1 回溯法(初步套用模板)
- 2 回溯法(swap优化)
1 回溯法(初步套用模板)
以下代码可以更好的理解模板的使用
代码语言:javascript复制class Solution {
private:
int size;
vector<vector<int>> solution;
vector<int> path; // 路径
public:
void backtrack(vector<int>& nums, unordered_set<int>& select_set) {
if (select_set.empty()) {
solution.emplace_back(path);
return;
}
for (int i = 0; i < size; i ) {
// if 选择nums[i]不在选择列表select_set中, then continue
if (!select_set.count(nums[i])) continue;
path.emplace_back(nums[i]); // 做选择
select_set.erase(nums[i]); // 从选择列表中移除该选择
backtrack(nums, select_set);
select_set.insert(nums[i]); // 从选择列表中恢复该选择
path.pop_back(); // 撤销选择
}
}
vector<vector<int>> permute(vector<int>& nums) {
size = nums.size();
// 选择列表
unordered_set<int> select_set(nums.begin(), nums.end());
backtrack(nums, select_set);
return solution;
}
};
这里专门额外开辟了一个包含原数据的选择列表unordered_set<int> select_set
,如果数据过大则会消耗很多存储,因此使用bool
类型的选择列表会降低一些内存消耗,具体修改如下
class Solution {
private:
int size;
vector<int> path;
vector<vector<int>> solution;
public:
void backtrack(vector<int>& nums, vector<bool>& inPath) {
if (path.size() == size) {
solution.emplace_back(path);
return;
}
for (int i = 0; i < size; i ) {
if (inPath[i]) continue;
inPath[i] = true;
path.emplace_back(nums[i]);
backtrack(nums, inPath);
path.pop_back();
inPath[i] = false;
}
}
vector<vector<int>> permute(vector<int>& nums) {
size = nums.size();
vector<bool> inPath(size, false);
backtrack(nums, inPath);
return solution;
}
};
2 回溯法(swap优化)
但全排列其实还可以进一步优化
代码语言:javascript复制class Solution {
private:
vector<vector<int>> solution;
int size;
public:
void backtrack(vector<int>& nums, int first) {
if (first == size) {
solution.emplace_back(nums);
return;
}
for (int i = first; i < size; i ) {
// 这里的notValid判断隐含在for循环的(i = first)中
swap(nums[first], nums[i]);
backtrack(nums, first 1);
swap(nums[first], nums[i]);
}
}
vector<vector<int>> permute(vector<int>& nums) {
size = nums.size();
backtrack(nums, 0);
return solution;
}
};