本文主要介绍两种全排列的获取方式。
方式一:代码如下。主要思想是首先选择第一个数,有n中选择,选择后标记,下次不可以再选择。然后选择第二个数,此时有n-1中选择,选择后标记,一次类推。n个数都选择好了,就是一次排列。然后将状态恢复。本代码使用了位运算,适合n小于32的情况。如果n比较大,需要借助额外的空间。
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> result = new ArrayList<>();
List<Integer> output = new ArrayList<>();
permute(nums,0,result,output);
return result;
}
public void permute(int[] nums, int mask, List<List<Integer>> result, List<Integer> output) {
if(output.size() == nums.length) {
result.add(new ArrayList<Integer>(output));
return;
}
for(int i = 0; i < nums.length; i++) {
if(((mask>>i) & 1) == 0) {
mask |= (1<<i);
output.add(nums[i]);
// 访问下一个
permute(nums,mask,result,output);
//恢复状态
mask ^= (1<<i);
output.remove(output.size()-1);
}
}
}
**方式二:**代码如下。主要采用交换的方式。每次都将当前元素和后面的元素交换位置。
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> result = new ArrayList<>();
List<Integer> output = new ArrayList<>();
for(int num : nums) {
output.add(num);
}
permute(output,result,0);
return result;
}
public void permute(List<Integer> output, List<List<Integer>> result, int start) {
if(start == output.size()) {
result.add(new ArrayList<>(output));
return;
}
for(int i = start; i < output.size(); i++) {
//交换
Collections.swap(output,start, i);
// 访问下一个
permute(output, result, start+1);
//恢复
Collections.swap(output,start, i);
}
}