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 };

 

posted @ 2020-12-29 14:02  habibah_chang  阅读(89)  评论(0编辑  收藏  举报