zoukankan      html  css  js  c++  java
  • 【LeetCode】046. Permutations

    题目:

    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;
        }
    };
  • 相关阅读:
    串口RS232和485通信的波形分析
    Ubuntu添加中文输入法
    虚拟机桥接模式联网方法,Xshell的连接与使用
    waitpid 函数详解
    linux for循环 fork() 产生子进程
    【LeetCode解题总结】动态规划篇
    【LeetCode解题总结】递归篇
    【LeetCode解题总结】排序篇
    【LeetCode解题总结】树/图篇
    【LeetCode解题总结】栈/队列篇
  • 原文地址:https://www.cnblogs.com/Atanisi/p/6766880.html
Copyright © 2011-2022 走看看