46. Permutations
关联问题:排列1:46. Permutations, 排列2:47. Permutations II,组合:77. Combinations
问题:
给定一个数组,求对该数组进行全排列的所有结果。
Example 1: Input: nums = [1,2,3] Output: [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]] Example 2: Input: nums = [0,1] Output: [[0,1],[1,0]] Example 3: Input: nums = [1] Output: [[1]] Constraints: 1 <= nums.length <= 6 -10 <= nums[i] <= 10 All the integers of nums are unique.
解法:Backtracking(回溯算法)DFS(深度优先搜索 Depth-First-Search)
回溯算法框架:
1 result = [] 2 def backtrack(路径, 选择列表): 3 if 满足结束条件: 4 result.add(路径) 5 return 6 7 for 选择 in 选择列表: 8 做选择 9 backtrack(路径, 选择列表) 10 撤销选择
对于本问题,两个变量:
- 路径:已经选择好的前几位结果
- 选择列表:对每个位置上元素的选择可能性
处理过程:
- base:递归退出条件:选择到最后一位结束,这里为已经选择好路径长度==给出的数组长度。
- 做选择:对于当前位置,选择其中一个可用数字a。
- 路径.add(a)
- 选择列表.delete(a)
- 撤销选择:回退到选择数字a之前的状况。
- 路径.delete(a)
- 选择列表.add(a)
代码参考:
1 class Solution { 2 public: 3 void traverse(vector<int> path, vector<int> nums) { 4 if(nums.empty()) { 5 result.push_back(path); 6 return; 7 } 8 for(int i=0; i<nums.size(); i++) { 9 vector<int> numstmp(nums); 10 path.push_back(nums[i]); 11 numstmp.erase(numstmp.begin()+i); 12 traverse(path, numstmp); 13 path.pop_back(); 14 } 15 return; 16 } 17 vector<vector<int>> permute(vector<int>& nums) { 18 vector<int> path; 19 traverse(path, nums); 20 return result; 21 } 22 private: 23 vector<vector<int>> result; 24 };
改进:
每次新建numstmp,太耗费内存,
-> 在做选择的时候,path中如果已经存在【选择列表】中的元素。说明该元素已被占用,则continue,不进行尝试。
要判断是否存在,vector中没有很好的方法,因此,引入unordered_set 等同path所存储内容。
使用count方法进行判断是否存在。
代码参考:
1 class Solution { 2 public: 3 void traverse(vector<int> path, vector<int> nums, unordered_set<int> pathset) { 4 if(path.size()==nums.size()) { 5 result.push_back(path); 6 return; 7 } 8 for(int i=0; i<nums.size(); i++) { 9 if(pathset.count(nums[i])!=0) continue; 10 path.push_back(nums[i]); 11 pathset.insert(nums[i]); 12 traverse(path, nums, pathset); 13 path.pop_back(); 14 pathset.erase(nums[i]); 15 } 16 return; 17 } 18 vector<vector<int>> permute(vector<int>& nums) { 19 vector<int> path; 20 unordered_set<int> pathset; 21 traverse(path, nums, pathset); 22 return result; 23 } 24 private: 25 vector<vector<int>> result; 26 };
改进:swap方法
对给定数组,进行元素交换,所得数组即为一个解。
1 class Solution { 2 public: 3 void traverse(vector<int> nums, int pos) { 4 if(pos==nums.size()) { 5 result.push_back(nums); 6 return; 7 } 8 for(int i=pos; i<nums.size(); i++) { 9 swap(nums[i], nums[pos]); 10 traverse(nums, pos+1); 11 swap(nums[i], nums[pos]); 12 } 13 return; 14 } 15 vector<vector<int>> permute(vector<int>& nums) { 16 traverse(nums, 0); 17 return result; 18 } 19 private: 20 vector<vector<int>> result; 21 };