算法笔记
在接连解决了组合,切割与子集等问题之后,本题会继续说明用回溯法解决的下一类问题 排列问题 ,需要弄清楚排列问题与以往问题有哪些相似处,哪些不同点。
题目描述
首先,题目给定了一个 不含重复数字 的数组,要得到全排列。这里就需要发现需要解决的主要问题就是得到一组包含所有全排列的结果,要求每组全排列都要有但不能有完全重复的项,所以也是需要使用某种方法去掉完全相同的排列,就可以想到used数组,用于标记已选择的数组。
解题步骤
三部曲:
1.选择参数: 在选择参数部分不再是老三样,只需要记录每项全排列的一维数组path,记录结果的二维数组path,但没有了之前问题所需的startIndex,这是因为排列有序,【1,2】与【2,1】代表两个集合,所以不适用。最后再加上标记重复的used数组即可。
2.终止条件: 全排列的项要与给定数组的元素个数相同,所以终止条件就可以认为当每个排列的长度等于给定数组长度即可解题path.size() == nums.size() 满足条件后使用result记录结果。
3.循环递归回溯: for循环内i是从0开始,如果之前的数组已被标记过,则代表它完全重复,这样它就不需要被记录,直接continue,其余步骤与以往问题一致进行递归回溯,至此解决问题。
代码实现
class Solution {
public:
vector<int> path;
vector<vector<int>> 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;
}
path.push_back(nums[i]);
used[i] = true;
backtracking(nums, used);
used[i] = false;
path.pop_back();
}
}
vector<vector<int>> permute(vector<int>& nums) {
vector<bool> used(nums.size(), false);
backtracking(nums, used);
return result;
}
};
结语
本题主要是解决排列问题,整体在理解used数组之后就会比较容易理解,如果对uesd数组不太理解,建议去看看组合总和问题II里面有比较完整的描述。