[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.解題思路app

此題爲求排列,與組合相比較,排列是順序相關的,可是已經被選中的數字是不能再次出現的,因此咱們想到維護一個isUsed[]數組來表示某個數字是否已被選中過。ui

2.代碼code

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.解題思路遞歸

包含重複的數字,因此咱們要對重複的排列序列進行排除,首先咱們對數組進行排序,而後當發現某個數與前一個數相同時,就判斷前一個數是否被選中,若是未被選中,則排除掉當前重複數,直接進入下一個;由於若是前一個數已被選中,說明如今正處於前一個數的遞歸選數字過程當中,則不能排除當前重複數。rem

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.get

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.it

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();
    }
}
相關文章
相關標籤/搜索