46. Permutations(java,无重复元素,字典序 + 非字典序)

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

解析:本题可以有两种方法解决

方法一:1)将第一个元素依次与所有元素进行交换;

2)交换后,可看作两部分:第一个元素及其后面的元素;

3)后面的元素又可以看作一个待排列的数组,递归,当剩余的部分只剩一个元素时,得到一个排列;

4)将第1步中交换的元素还原,再与下一个位元素交换。

重复以上4步骤,直到交换到最后一个元素。(参考剑指offer讲解)

方法二:字典序,根据当前序列,生成下一个序列,交换 + 逆序。

代码:

方法一:非字典序

public static void main(String[] args) {
        // TODO Auto-generated method stub

        //定义数组
        int[] array = {1,2,3};
        List<List<Integer>> list = new ArrayList<List<Integer>>();
        int start = 0;

        //不去重,非字典序
        list = getPermutations(array, list, start);
    }
    /**
     * 方法一
     * 不去重,非字典序
     * @param array
     * @return
     */
    public static List<List<Integer>> getPermutations(int[] array,List<List<Integer>> list,int start){
        if(start == array.length){//遍历到最后一个,得到一个排列
            List<Integer> item = new ArrayList<Integer>(array.length);
            for(int i = 0,len = array.length; i < len; ++i)
                item.add(array[i]);
            list.add(item);
        } else {
            //需要交换的次数
            for(int i = start,len = array.length; i < len; ++i){ //第一个元素,依次与后面的所有元素进行交换
                //交换
                swap(array,i,start);
                //递归在循环里
                getPermutations(array,list,start + 1); //字符串分为两部分,第一个元素及第一个元素之后的所有元素
                //回溯
                swap(array,i,start);
            }
        }

        return list;
    }

方法二:字典序,调用next permutation

    /**
     * 方法二
     * 不去重,字典序
     * @return
     */
    public static List<List<Integer>> permutations(int[] array,List<List<Integer>> list){

        //一共需要进行 n! 次运算
        for(int i = 0,len = factorial(array.length); i < len; ++i){
            if(i == 0){
                List<Integer> item = new ArrayList<Integer>();
                for(int j = 0,l = array.length; j < l; ++j)
                    item.add(array[j]);
                list.add(item);
            } else {
                List<Integer> item = new ArrayList<Integer>();
                item = nextPermutation(array);
                list.add(item);
            }
        }
        return list;
    }

    /**
     * 获取下一个字典序的排列
     * @return
     */
    public static List<Integer> nextPermutation(int[] nums){
        if(nums == null)
            return null;
        if(nums.length == 0)
            return new ArrayList<Integer>();
        //长度为1的数组
        if (nums.length == 1) {
            return new ArrayList<Integer>(nums[0]);
        }
        //存储结果
        List<Integer> result = new ArrayList<Integer>();

        //从后向前找到第一个不满足逆序的元素
        int i = nums.length - 2;
        for(; i >= 0 && nums[i] > nums[i + 1]; --i);

        //从i+1位置开始,向后查找比nums[i]大的最小元素
        if(i >= 0){
            int j = i + 1;
            for(; j < nums.length && nums[j] > nums[i]; ++j);
            swap(nums,i,j - 1); //交换,注意是同 j - 1交换
        }

        //将i之后的元素逆置(这里包含一种特殊情况,若该排列已经是字典序中的最大了,则下一个序列应该是最小字典序,因此,直接在这里逆置即可)
        int k = nums.length - 1;
        i++;
        for(; i < k; i++, k--)
            swap(nums, i, k);

        for(int l = 0,len = nums.length; l < len; ++l)
            result.add(nums[l]);

        return result;
    }
时间: 2024-10-27 13:25:06

46. Permutations(java,无重复元素,字典序 + 非字典序)的相关文章

求全排列(数组有重复元素和数组无重复元素) 回溯 递归

http://www.cnblogs.com/TenosDoIt/p/3662644.html 无重复元素 http://blog.csdn.net/havenoidea/article/details/12838479 有重复元素

无重复元素的排列

/*========================================================== 设有n个整数的集合{1,2,3,......,n},从中任意选择r个数进行排列. 其中r<n,请列出所有排列. 思路:递归r层,每层选择一个数放到a[].当递归到r层时得到一组排列. 在每一层中做选择的时候,要把所有可能的选择都进行尝试. 具体看代码. ============================================================*/

leetcode 46 Permutations ----- java

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] ] 给定一个数组,求所有的排列组合. 做出这道题很简单,主要是要比较快的速度,第一次做,耗时5ms,比较慢,主要就是用递归,每次向arr

数据结构---无重复元素链表的实现

//节点结构体 struct inv { int i;//节点元素 struct inv*nextpointer; }; //返回指定元素节点的指针,不包含时返回NULL struct inv* contain(int i,struct inv*head) { struct inv *headp=head; while(headp!=NULL) { if(headp->i==i) { break; } headp=headp->nextpointer; } return headp; } //

46. Permutations java solutions

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] ] Subscribe to see which companies asked this question 1 public clas

[LeetCode系列]子集枚举问题[无重复元素]

给定一组数(未排序), 求它们的所有组合可能. 如给定{1 2 3}, 返回: [ [] [1] [2] [3] [1 2] [1 3] [2 3] [1 2 3] ] 算法思路: 对数组排序, 从小到大; 令 i = 0, 对已有组合v从后往前进行如下操作 v的最后1个组合内加入第i个元素; 将新组合加入到v中 算法的理解可以通过一个例子来看: 给定S = {1 2 3}, v = [[]] i = 0, j = 1, v = [[] [1]] // back().push_back(S[0]

含有重复元素的排列

Description 设R={ r1, r2, ……, rn }是要进行排列的n个元素.其中元素r1 ,r2 ,……,rn可能相同.试设计一个算法,列出R的所有不同排列.给定n以及待排列的n个元素.计算出这n个元素的所有不同排列. Input 输入数据的的第1行是元素个数n,1≤n≤500.接下来的1行是待排列的n个元素. Output 将计算出的n个元素的所有不同排列输出,每种排列占1行,最后1行中的数是排列总数. Sample Input 4 aacc Sample Output aacc

Perl快捷删除数组重复元素,以前写过类似的博客,今天被问起时,却支支吾吾!

以前写过类似的博客: http://blog.csdn.net/three_man/article/details/34084361 今天拿出来,再好好剖析一下: 1. 构造一个含有重复元素的数组 my @arr1 = (1 .. 10); my @arr2 = (5 .. 15); # join multi array my @arr = (@arr1, @arr2); 2. 删除数组中的重复元素 sub removeRepeat { my $arrRef = shift; my %count

[LeetCode系列]子集枚举问题[有重复元素]

给定一组数(未排序, 可能有重复元素), 求出所有可能的组合. 算法和无重复元素的相似. 唯一需要注意的是, 如果当前的数字和之前的相同, 算法就只会在结尾数字是此数字的组合后加上此数字. 比如现在是[[] [1] [1 2] [2]], 当前数字是2, 就只会增加[1 2 2] [2 2] 代码: 1 class Solution { 2 public: 3 vector<vector<int> > subsetsWithDup(vector<int> &S)