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(); } }