今日主要总结一下,46. 全排列
题目:46. 全排列
题目描述:
给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。
示例 1:
输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
示例 2:
输入:nums = [0,1]
输出:[[0,1],[1,0]]
示例 3:
输入:nums = [1]
输出:[[1]]
提示:
1 <= nums.length <= 6
-10 <= nums[i] <= 10
nums 中的所有整数 互不相同
本题重难点
首先要搞懂排列和组合以及子集问题的区别:
首先排列是有序的,也就是说 [1,2] 和 [2,1] 是两个集合,这和之前分析的组合以及子集所不同的地方。
可以看出元素1在[1,2]中已经使用过了,但是在[2,1]中还要在使用一次1,所以处理排列问题就不用使用startIndex了。
但排列问题需要一个used数组,标记已经选择的元素,如图橘黄色部分所示:
看一下这道题抽象成的树形图:
而used数组,其实就是记录此时path里都有哪些元素使用了,一个排列里一个元素只能使用一次。
一、正确解法
C++代码
class Solution {
public:
vector<int> path;
vector<vector<int>> res;
vector<bool> used;
void backtracing(vector<int>& nums, vector<bool>& used){
if(path.size() == nums.size()){
res.push_back(path);
return;
}
for(int i = 0; i < nums.size(); i++){
//注意和组合以及子集问题的区别,之前for循环每层都是从startIndex开始取
//排列每层都是从0开始搜索而不是startIndex
if(used[i] == true) continue;
path.push_back(nums[i]);
used[i] = true;
backtracing(nums, used);
used[i] = false;
path.pop_back();
}
return;
}
vector<vector<int>> permute(vector<int>& nums) {
res.clear();
path.clear();
used.resize(nums.size(), false);
backtracing(nums, used);
return res;
}
};
总结
首先要搞懂排列和组合以及子集问题的区别:
首先排列是有序的,也就是说 [1,2] 和 [2,1] 是两个集合,这和之前分析的组合以及子集所不同的地方。
可以看出元素1在[1,2]中已经使用过了,但是在[2,1]中还要在使用一次1,所以处理排列问题就不用使用startIndex了。
大家此时可以感受出排列问题的不同:
- 每层都是从0开始搜索而不是startIndex
- 排列问题需要一个used数组,标记已经选择的元素,而used数组,其实就是记录此时path里都有哪些元素使用了,一个排列里一个元素只能使用一次。
排列问题是回溯算法解决的经典题目,大家可以好好体会体会。
欢迎大家关注本人公众号:编程复盘与思考随笔
(关注后可以免费获得本人在csdn发布的资源源码)
公众号主要记录编程和刷题时的总结复盘笔记和心得!并且分享读书、工作、生活中的一些思考感悟!