46. Permutations&&47. Permutations II&31. Next Permutation

来源:互联网 发布:延迟选择实验 知乎 编辑:程序博客网 时间:2024/06/01 11:10

找到一个非常好的讲全排列的贴http://blog.csdn.net/morewindows/article/details/7370155

hin清楚!


46


一开始想用backtracking再加一个判断前面的值是否调用过的矩阵做,但是后来觉得很麻烦耶……

看了discuss发现有一个如此机智的办法.

对于给定的A来说,对每个A[i],分别将其和A[0]交换。这样A[0...N]都会在A[0]的位置上出现。

然后对于每个在A[0]位置上的A[I], 再分别把A[1]和A[N]交换,这样保证A[1...N]都会在A[1]的位置上出现。

代码:

class Solution {public:    vector<vector<int>> res;        vector<vector<int>> permute(vector<int>& nums) {                helper(nums,0);        return res;    }        void helper(vector<int> nums,int begin){                if(begin==nums.size()) {res.push_back(nums);return;}        for(int i=begin;i<nums.size();i++){            swap(nums[i],nums[begin]);            helper(nums,begin+1);            swap(nums[i],nums[begin]);        }    }};

有一个作弊的做法是用vector自带的next_permutaion函数,真是……

class Solution {public:    vector<vector<int>> res;        vector<vector<int>> permute(vector<int>& nums) {            sort(nums.begin(),nums.end());    res.push_back(nums);    while(next_permutation(nums.begin(),nums.end()))    {        res.push_back(nums);    }        return res;    }    };

47

以为会很快,不就是46再加一个remove duplicates的条件吗……然后写了两个小时……

一开始的时候加了一个条件

if(begin!=i&&(nums[i]==nums[i-1]||nums[i]==nums[begin])){                continue;            }
然鹅还是WA了

后来发现问题出在这里:

class Solution {public:    vector<vector<int>> permuteUnique(vector<int>& nums) {                vector<vector<int>> res;                sort(nums.begin(),nums.end());                permutation(nums,res,0);                return res;            }        void permutation(vector<int>& nums,vector<vector<int>>& res,int begin){                if(begin==nums.size()) {res.push_back(nums); return;}                for(int i=begin;i<nums.size();i++){                if(begin!=i&&(nums[i-1]==nums[i]||nums[i]==nums[begin])){                continue;            }            swap(nums[i],nums[begin]);            permutation(nums,res,begin+1);            swap(nums[i],nums[begin]);        }    }};

我一开始的做法是沿用上一题的套路,传递参数时使得nums可以被修改,然后在调用完后再swap调整回去。

但是在这道题里不适用。因为如果中途修改了nums的话,会令Nums不再是一个排好序的数组,这样的话判断条件就会失效。

例如1122334这个例子,在第2个2与第1个和第2个3分别交换的时候,就会产生duplicates。有兴趣可以试一下。

这道题的判断条件其实应该是:交换begin和i的时候,要保证begin和i之间没有和i相等的值存在。

但是我看别人的代码发现只要修改一下nums的操作方式就可以了

class Solution {public:    vector<vector<int>> permuteUnique(vector<int>& nums) {                vector<vector<int>> res;                sort(nums.begin(),nums.end());                permutation(nums,res,0,nums.size());                return res;            }        void permutation(vector<int> nums,vector<vector<int>>& res,int begin,int end){                if(begin==end-1) {res.push_back(nums); return;}                for(int i=begin;i<end;i++){                if(begin!=i&&(nums[i]==nums[i-1]||nums[i]==nums[begin])){                continue;            }            swap(nums[i],nums[begin]);            permutation(nums,res,begin+1,end);            //swap(nums[i],nums[begin]);        }    }};
每次调用函数时采用值传递而不是引用传递的方法,不懂耶……

31是求下一个排列,这里有一篇文章讲的很好http://blog.csdn.net/qq575787460/article/details/41215475

class Solution {public:    void nextPermutation(vector<int>& nums) {                int n=nums.size();        int i=n-1;                while(i>0&&nums[i]<=nums[i-1]){//要用等于号remove duplicates            i--;        }                if(i==0) {reverse(nums.begin(),nums.end()); }        else{            i--;            int j=n-1;            while(j>i&&nums[j]<=nums[i]) j--;//要用等于号remove duplicates            swap(nums[i],nums[j]);            vector<int>:: iterator it=nums.begin();            reverse(it+i+1,nums.end());        }    }};




0 0
原创粉丝点击