题意:给定一个包含不同数的集合(len个),返回所有的排序(全排序)。
思路:先算出全排序的个数(n!),然后循环n!次,每次根据pre(上一个排序)来求cur(当前排序)nextPermutations实现,并将cur添加到输出结果,然后设定pre = cur来用于求下一个排序
代码:
public class Solution {
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> res = new ArrayList<List<Integer>>();
int len = nums.length, c = 1;
Arrays.sort(nums);
// 计算总共多少个len:n!
for(int i=1; i<=len; i++) {
c *= i;
}
Integer[] num = new Integer[len];
for(int i=0; i<len; i++) {
num[i] = nums[i];
}
List<Integer> pre = Arrays.asList(num);
res.add(pre);
for(int i=1; i<c; i++) { // len个元素,有len!个Permutations
List<Integer> cur = nextPermutations(pre);
res.add(cur);
pre = cur;
}
return res;
}
// 查找当前排列的下一个字典序排列:仍然使用三部曲
public List<Integer> nextPermutations(List<Integer> cur) {
List<Integer> next = new ArrayList<Integer>();
int len = cur.size();
int pos = -1;
Integer[] nums = (Integer[])cur.toArray(new Integer[len]);
// 从nums右边开始,找到第一个升序元素下标
for(int i=len-1; i>=0; i--) {
if(i-1 >=0 && nums[i] > nums[i-1]) {
pos = i-1;
break;
}
}
// 判断pos是否找到。若没找到,则证明nums是降序的,直接反转即可得到nums的下一个排序
if(pos == -1) {
reverse(nums, 0, len-1);
next = Arrays.asList(nums);
return next;
}
// pos找到后,在[pos+1, len-1]之间,从右边开始,找到第一个大于nums[pos]的值,并与nums[pos]交换
for(int i=len-1; i>pos; i--) {
if(nums[i] > nums[pos]) {
int tmp = nums[i];
nums[i] = nums[pos];
nums[pos] = tmp;
break;
}
}
reverse(nums, pos+1, len-1);
next = Arrays.asList(nums);
return next;
}
public void reverse(Integer[] nums, int left, int right) {
int tmp = 0;
while(left < right) {
tmp = nums[left];
nums[left] = nums[right];
nums[right] = tmp;
left++;
right--;
}
}
}