回溯算法:
利用backtrack函数,当没满足条件时就依次枚举nums,如果在此前未加入过则选择该数nums[i],然后继续调用backtrack函数,调用完后需要释放选择的数nums[i]。
当满足条件后(当前数组长度等于nums的长度),则添加进答案里
原始代码:
class Solution {
public:
vector<vector<int>> ans;
vector<vector<int>> permute(vector<int>& nums) {
vector<int> curr;
vector<bool> used(nums.size(), false);
backtrack(curr, nums, used);
return ans;
}
void backtrack(vector<int> curr, vector<int> nums, vector<bool> used) {
if (curr.size() == nums.size()) {
ans.push_back(curr);
return;
}
for (int i = 0;i < nums.size();i++) {
if (used[i] == false) {
curr.push_back(nums[i]);
used[i] = true;
backtrack(curr, nums, used);
curr.pop_back();
used[i] = false;
}
}
}
};
以上代码每次调用backtrack都需要计算nums长度,又反复修改curr数组,造成了时间上的损耗,针对以上两点进行了优化:
①提前计算并传入nums长度
②不创建curr和used数组而是动态维护原nums数组。通过直接在原数组中对两个数进行交换来达到相同的效果
class Solution {
public:
vector<vector<int>> ans;
vector<vector<int>> permute(vector<int>& nums) {
backtrack(nums, 0, nums.size());
return ans;
}
void backtrack(vector<int> &nums, int begin,int n) {
if (n == begin) {
ans.push_back(nums);
return;
}
for (int i = begin;i < nums.size();i++) {
swap(nums[i], nums[begin]); // 直接依次交换begin和其他数的位置
//因为begin之前的数已经和它交换过,因此只需换后面的
backtrack(nums, begin + 1, n);
swap(nums[i], nums[begin]); // 回溯后再换回来
}
}
};