46. Permutations

一、题目

  1、审题

  2、分析:

    输入一个不重复整形数组,求他的全排序

二、解答

  1、思路:

    方法一:利用递归实现全排序,先固定第一个值,在对后边全排序...最终当固定的值为最大下标时,则此时即得一排序。

class Solution {
    public List<List<Integer>> permute(int[] nums) {
        Arrays.sort(nums);
        
        List<List<Integer>> resultList = new ArrayList<List<Integer>>();
        
        callAllPerm(resultList, nums, 0, nums.length - 1);
        
        return resultList;
    }
    
    // 获得全排序
    private void callAllPerm(List<List<Integer>> resultList, int[] nums, int from,
            int to) {
    
        if(from == to) {    // add
            List<Integer> list = new ArrayList<Integer>();
            for (int i = 0; i < nums.length; i++) {
                list.add(nums[i]);
            }
            resultList.add(list);
        }
        else {
            for (int i = from; i <= to; i++) {
                swap(nums, i, from);
                callAllPerm(resultList, nums, from + 1, to);
                swap(nums, i, from);
            }
        }
    }
    
    // 交换数组元素
    private void swap(int[] nums, int tempIndex, int index) {
        int temp = nums[tempIndex];
        nums[tempIndex] = nums[index];
        nums[index] = temp;
    }
}

  

  方法二:  将数组排成升序后,依次求得比这一个数组数字大的下一个数字数组,最终这些所有的字典序的数组即为全排序。

        求字典序步骤如下,例如对于 21543而言,其下一个排序序列求法为:

        ①、从右向左找到第一个能有升序的位置i ,此时,x = ai = 1;

        ②、在 i 的右侧找到比 ai 大的最小的一个元素位置 j, 此时, y = aj = 3;(其实就是从右向左查找的第一个比 ai 大的数就是了)

        ③、交换 x 与 y

        ④、将 i + 1 到最后位置的数组元素进行翻转。

class Solution {
    public List<List<Integer>> permute(int[] nums) {
        List<List<Integer>> resultList = new ArrayList<List<Integer>>();
        if(nums.length == 0)
            return resultList;
        
        Arrays.sort(nums);
        
        addTargetList(resultList, nums);    //加上原排序
        
        helper(resultList, nums, nums.length - 2);
        
        return resultList; 
    }
    
    /*
     *     1、交换
     *     2、翻转
     *     3、i 改变
     */
    private void helper(List<List<Integer>> resultList, int[] nums, int index) {
        
        if(index < 0)
            return;
        
        int tempIndex = -1;
        for (int i = nums.length -1; i > index; i--) {
            // 找比 index 大的最小值
            if(nums[i] > nums[index]) {
                tempIndex = i;
                break;
            }
        }
        
        if(tempIndex != -1) {
            swap(nums, tempIndex, index);        //交换
            reverse(nums, index+1);                // 翻转
            addTargetList(resultList, nums);    // 添加
            helper(resultList, nums, nums.length - 2);    // 重新递归
        }
        else {
            helper(resultList, nums, index - 1);    // index 向左移动
        }
    }

    private void addTargetList(List<List<Integer>> resultList, int[] nums) {
        List<Integer> list = new ArrayList<Integer>();
        for (int i = 0; i < nums.length; i++) {
            list.add(nums[i]);
        }
        resultList.add(list);
    }

    // 翻转从 index 开始的数组元素
    private void reverse(int[] nums, int index) {
        if(index < nums.length - 1) {
            for (int i = index, j= nums.length-1; j > i; i++, j--) {
                swap(nums, i, j);
            }
        }
    }

    // 交换数组元素
    private void swap(int[] nums, int tempIndex, int index) {
        int temp = nums[tempIndex];
        nums[tempIndex] = nums[index];
        nums[index] = temp;
    }
}

        

原文地址:https://www.cnblogs.com/skillking/p/9633194.html