46. 全排列

题目链接:https://leetcode-cn.com/problems/permutations/

思路:
给定已知序列P = A0 A1 A2 ... An
对P按字典排序,得到P的一个最小排列Pmin = A0 A1 A2 ... A(n-1) ,满足Ai > A(i-1) (1 <= i < n)。因为这个算法的结果是没有重复的、排列从小到大排序的,如果不是最小的排列输入进去,那么排出来的只有比它字典序大的排列。
从Pmin开始,找到刚好比Pmin大的一个排列P(min+1),再找到刚好比P(min+1)大的一个排列,如此重复。
Step1:从后向前(即从A(n-1) -> A0),找到第一对为升序的相邻元素,即Ai < A(i+1)。
若找不到这样的Ai,说明已经找到最后一个全排列,可以返回了。
Step2:从后向前,找到第一个比Ai大的数Aj,交换Ai和Aj。
Step3:将排列中A(i+1) A(i+2) … A(n-1)这个序列的数逆序倒置,即A(n-1) ... A(i+2) A(i+1)。因为由前面第Step1、Step2可以得知,A(i+1) <= A(i+2) <= ... <= A(n-1),,为一个降序序列,应将该序列逆序倒置,所得到的新排列才刚刚好是上一个排列的下一个排列。
Step4:重复步骤1-3,直到返回(返回在Step1中)。
这个算法是C++ STL中next_permutation函数的思想。

图示:


上代码:

class Solution {
    public List<List<Integer>> permute(int[] nums) {
        //保证输入的nums[]是最小的排列,必须从小到大排序一下
        Arrays.sort(nums);
        List<List<Integer>> lists = new ArrayList<>();
        while (true) {
            List<Integer> arrayList = new ArrayList<>();
            for (int num : nums) {
                arrayList.add(num);
            }
            lists.add(arrayList);
            int i, j;
            for (i = nums.length - 2; i >= 0; i--) {
                if (nums[i] < nums[i + 1]) {
                    break;
                }
            }
            if (i == -1) {
                return lists;
            }
            for (j = nums.length - 1; j >= 0; j--) {
                if (nums[j] > nums[i]) {
                    break;
                }
            }
            int tmp = nums[i];
            nums[i] = nums[j];
            nums[j] = tmp;
            for (int left = i + 1, right = nums.length - 1; left < right; left++,right--) {
                tmp = nums[left];
                nums[left] = nums[right];
                nums[right] = tmp;
            }
        }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

心脏dance

如果解决了您的疑惑,谢谢打赏呦

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值