【LeetCode】046. Permutations

折月煮酒 提交于 2020-02-08 04:06:09

题目:

Given a collection of distinct numbers, return all possible permutations.

For example,
[1,2,3] have the following permutations:

[
  [1,2,3],
  [1,3,2],
  [2,1,3],
  [2,3,1],
  [3,1,2],
  [3,2,1]
]

  

题解:

  之前解过Next Permutation,故这个题可以重复调用nextPermutation函数产生全排列

Solution 1 ()

class Solution {
public:
    void nextPermutation(vector<int>& nums) {
        int n = nums.size();
        for(int i=n-2; i>=0; --i) {
            if(nums[i]>=nums[i+1]) continue;
            int j = n-1;
            for(; j>i; --j) {
                if(nums[j]>nums[i]) break;
            }
            swap(nums[i], nums[j]);
            reverse(nums.begin()+i+1, nums.end());
            return;            
        }
        reverse(nums.begin(), nums.end());
    }
    vector<vector<int>> permute(vector<int>& nums) {
        vector<vector<int>> vv;
        vector<int> v = nums;
        vv.push_back(v);
        nextPermutation(v);
        while(v != nums) {
            vv.push_back(v);
            nextPermutation(v);
        }
        return vv;
    }
};

  其实这个问题很容易想到递归的解法

  for the length of n, the permutations can be generated by
(1) Swap the 1st element with all the elements, including itself.
(2) Then the 1st element is fixed, Go to the next element.
(3) Until the last element is fixed. Output.
It's more clear in the figure above. The key point is to make the big problem into smaller problem, here is how to convert the length n permutation into length n-1 permutation problem. from here and here

Solution 2 ()

class Solution {
public:
    vector<vector<int> > permute(vector<int> &nums) {
        vector<vector<int> > result;        
        permuteRecursive(nums, 0, result);
        return result;
    } 
    // permute nums[begin..end]
    // invariant: nums[0..begin-1] have been fixed/permuted
    void permuteRecursive(vector<int> &nums, int begin, vector<vector<int> > &result)    {
        if (begin >= nums.size()) {
            // one permutation instance
            result.push_back(nums);
            return;
        }
        for (int i = begin; i < nums.size(); i++) {
            swap(nums[begin], nums[i]);
            permuteRecursive(nums, begin + 1, result);
            // reset
            swap(nums[begin], nums[i]);
        }
    }
};

  利用深度优先遍历遍历所有情况,DFS方法,用到一个数组来标记某个数字是否访问过,然后在DFS递归函数从的循环应从头开始,而不是从level开始,这是和Combinations 组合项不同的地方。

from here 

Solution 3 ()

class Solution {
public:
    vector<vector<int> > permute(vector<int> &nums) {
        vector<vector<int> > res;
        vector<int> out;
        vector<int> visited(nums.size(), 0);
        permuteDFS(nums, 0, visited, out, res);
        return res;
    }
    void permuteDFS(vector<int> &nums, int level, vector<int> &visited, vector<int> &out, vector<vector<int> > &res) {
        if (level == nums.size()) res.push_back(out);
        else {
            for (int i = 0; i < nums.size(); ++i) {
                if (visited[i] == 0) {
                    visited[i] = 1;
                    out.push_back(nums[i]);
                    permuteDFS(nums, level + 1, visited, out, res);
                    out.pop_back();
                    visited[i] = 0;
                }
            }
        }
    }
};

   思路: from here

当n=1时,数组中只有一个数a1,其全排列只有一种,即为a1

当n=2时,数组中此时有a1a2,其全排列有两种,a1a2和a2a1,那么此时我们考虑和上面那种情况的关系,我们发现,其实就是在a1的前后两个位置分别加入了a2

当n=3时,数组中有a1a2a3,此时全排列有六种,分别为a1a2a3, a1a3a2, a2a1a3, a2a3a1, a3a1a2, 和 a3a2a1。那么根据上面的结论,实际上是在a1a2和a2a1的基础上在不同的位置上加入a3而得到的。

_ a_ a_ : a3a1a2, a1a3a2, a1a2a3

_ a_ a_ : a3a2a1, a2a3a1, a2a1a3

Solution 4 ()

class Solution {
public:
    vector<vector<int> > permute(vector<int> &nums) {
        if (nums.empty()) return vector<vector<int> >(1, vector<int>());
        vector<vector<int> > res;
        int first = nums[0];
        nums.erase(nums.begin());
        vector<vector<int> > words = permute(nums);
        for (auto &a : words) {
            for (int i = 0; i <= a.size(); ++i) {
                a.insert(a.begin() + i, first);
                res.push_back(a);
                a.erase(a.begin() + i);
            }
        }   
        return res;
    }
};

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!