[Leetcode]PermutationsI II Next Permutation Permutation Sequence

Permutations
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]
]

1.解题思路

此题为求排列,与组合相比较,排列是顺序相关的,但是已经被选中的数字是不能再次出现的,所以我们想到维护一个isUsed[]数组来表示某个数字是否已被选中过。

2.代码

public class Solution {
    List<List<Integer>> res=new ArrayList<List<Integer>>();
    public List<List<Integer>> permute(int[] nums) {
        if(nums.length==0) return res;
        boolean[] isUsed=new boolean[nums.length];
        permuteHelper(nums,isUsed,nums.length,new ArrayList<Integer>());
        return res;
    }
    private void permuteHelper(int[] nums, boolean[] isUsed,int count,List<Integer> pre){
        if(count==0){
            res.add(pre);
            return;
        }
        for(int i=0;i<nums.length;i++){
            if(!isUsed[i]){
                List<Integer> cur=new ArrayList<Integer>(pre);
                cur.add(nums[i]);
                isUsed[i]=true;
                permuteHelper(nums,isUsed,count-1,cur);
                isUsed[i]=false;
            }
        }
    }
}

Permutations II
Given a collection of numbers that might contain duplicates, return all possible unique permutations.

For example,
[1,1,2] have the following unique permutations:
[
  [1,1,2],
  [1,2,1],
  [2,1,1]
]

1.解题思路

包含重复的数字,所以我们要对重复的排列序列进行排除,首先我们对数组进行排序,然后当发现某个数与前一个数相同时,就判断前一个数是否被选中,如果未被选中,则排除掉当前重复数,直接进入下一个;因为如果前一个数已被选中,说明现在正处于前一个数的递归选数字过程中,则不能排除当前重复数。

public class Solution {
    List<List<Integer>> res=new ArrayList<List<Integer>>();
    public List<List<Integer>> permuteUnique(int[] nums) {
        if(nums.length==0) return res;
        Arrays.sort(nums);
        permuteUniqueHelper(nums,new boolean[nums.length],nums.length,new ArrayList<Integer>());
        return res;
    }
    private void permuteUniqueHelper(int[] nums,boolean[] used,int count, List<Integer> pre){
        if(count==0){
            res.add(pre);
            return;
        }
        for(int i=0;i<nums.length;i++){
            if(i>0&&nums[i]==nums[i-1]&&!used[i-1]) continue;
            List<Integer> cur=new ArrayList<Integer>(pre);
            if(!used[i]){
                cur.add(nums[i]);
                used[i]=true;
                permuteUniqueHelper(nums,used,count-1,cur);
                used[i]=false;
            }
        }
    }
}

Next Permutation
Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers.

If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending order).

The replacement must be in-place, do not allocate extra memory.

Here are some examples. Inputs are in the left-hand column and its corresponding outputs are in the right-hand column.
1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1

1.解题思路

这道题是要将排列按字典序排列,然后求出下一个排列,一种办法是我们先求出所有的排序情况,但是题目规定不能占有额外空间。根据example, 我们发现其实我们可以从数组后面开始比较相邻的两个数,如果后面的数小于前面的数,则继续往前;如果后面的数大于前面的数,将前面那个数下标标记为i-1,则我们知道i-1这个数的位置是需要交换,那和后面的哪个交换呢?肯定是和从i开始往后找比i-1数大,但是又是后面最小的数作交换。
这样i-1这个位置的数就确定下来了。因为刚才我们一路上数组末尾往前,经过的数字都是逆序的,我们现在要做的就是反转这些数,这样就得到了next permutation.

public class Solution {
    public void nextPermutation(int[] nums) {
        if(nums.length==0) return;
        int i=nums.length-1;
        for(;i>0;i--){
            if(nums[i]>nums[i-1]) break;
            
        }
        if(i==0) {
            reverse(nums,0,nums.length-1);
            return;
        }
        int first=i-1; //the first num need to be swapped.
        int nextbig=nums[i];
        int nextbig_index=i;
        for(int j=i+1;j<nums.length;j++){
            if(nextbig>=nums[j]&&nums[j]>nums[first]){
                nextbig=nums[j];
                nextbig_index=j;
            }
        }
        swap(nums,first,nextbig_index);
        reverse(nums,first+1,nums.length-1);
    }
    private void reverse(int[] nums, int start,int end){
        while(start<end){
            swap(nums,start,end);
            start++;
            end--;
        }
    }
    private void swap(int[] nums, int left,int right){
        int temp=nums[left];
        nums[left]=nums[right];
        nums[right]=temp;
    }
}

Permutation Sequence
The set [1,2,3,…,n] contains a total of n! unique permutations.

By listing and labeling all of the permutations in order,
We get the following sequence (ie, for n = 3):

"123"
"132"
"213"
"231"
"312"
"321"

Given n and k, return the kth permutation sequence.

Note: Given n will be between 1 and 9 inclusive.

1.解题思路

这个题目其实涉及到一些数学规律,我们仔细看例子会发现其实以每个数字开头的序列都会有(n-1)!个,所以我们只要用k/(n-1)!就可以得到第一个数字,在求出第一个数字后,我们只要将k%(n-1)!,就可以继续循环求第二个数。
需要注意的地方有:
1)代码里我们是把数字放入了一个List中,而list的下标是以0开始的,所以我们首先将k-1。
2)每次求出一个数字后,要及时的把它从List中删除掉。
3)采用StringBuilder来构造结果序列。

2.代码

public class Solution {
    public String getPermutation(int n, int k) {
        List<Integer> nums=new ArrayList<Integer>();
        int factorial=1;
        int i=1;
        while(i<=n){
            factorial*=i;
            nums.add(i);
            i++;
        }
        k--; 
        int j=n;
        StringBuilder sb=new StringBuilder();
        while(nums.size()>0){
            factorial=factorial/j;
            int index=k/factorial;
            sb.append(nums.get(index));
            nums.remove(index);
            j--;
            k=k%factorial;
        }
        
        return sb.toString();
    }
}
  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值