码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2016-08-13 12:35:52      阅读:150      评论:0      收藏:0      [点我收藏+]

标签:

题目: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;
    }

 

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

标签:

原文地址:http://www.cnblogs.com/mydesky2012/p/5767719.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!