lintcode 全排列

给定一个数字列表,返回其所有可能的排列,第十五题是没有重复的数字,是十六题是有重复的数字。
先来说没有重复数字的情况
n个数字有n!个全排列,每个数字都可以成为排列的第一个数字,然后剩下n-1个数字里可以找出第二个数字,之后剩下的n-2个数字里可以找到第三个数字,依次类推,最后只有一个数字可以放在第n个位置,因此可以采用回溯法,也可以叫做深度优先搜索。
我们以数组[1,2,3]为例,首先进入第一个for循环,i和start都为0,执行swap,此时为1和自身交换,接着进入递归,i和start都为1,执行swap,此时为2和自身交换,接着进行递归(start为2),3和自身交换,此时start等于了数组的长度,因此返回,得到的一个排列为[1,2,3]。然后返回上一层的递归函数(start为2),执行swap,3和自身交换,再返回上一层(start为1),执行swap,2和自身交换。接着进入下一个for循环(此时i和start都为1,而循环条件为i 说的比较啰嗦,代码如下:

class Solution {
public:
    /**
     * @param nums: A list of integers.
     * @return: A list of permutations.
     */
    vector > permute(vector nums) {
        // write your code here
        vector> result;
        permutation(nums,result,0,nums.size());
        return result;
    }
    void permutation(vector num,vector > &res,int start,int end) {
        if (start == end) {
            res.push_back(num);
            return;
        }
        for (int i = start;i < end;i++) {
            swap(num[i],num[start]);
            permutation(num,res,start+1,end);
            swap(num[i],num[start]);
        }
    }
};

接下来是有重复数字的情况,大体的思路和没有重复数字的是一样的,但是如果swap两个一样的数字,就会产生重复,因此,加入一个条件判断,为了保证重复的数字都挨着,首先将数组进行排列。代码如下:

class Solution {
public:
    /**
     * @param nums: A list of integers.
     * @return: A list of unique permutations.
     */
    vector > permuteUnique(vector &nums) {
        // write your code here
        sort(nums.begin(),nums.end());
        vector > result;
        permutation(result,nums,0);
        return result;
    }
    void permutation(vector > &res,vector num,int start) {
        if (start == num.size()) {
            res.push_back(num);
            return;
        }
        for (int i = start;i < num.size();i++) {
            if (start != i && num[start] == num[i]) continue;
            swap(num[start],num[i]);
            permutation(res,num,start + 1);
        }
    }
};

你可能感兴趣的:(lintcode 全排列)