import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
public class Permutation {
//方法一:回溯
public List<List<Integer>> permute1(int[] nums) {
//定义保存结果的list
ArrayList<List<Integer>> result = new ArrayList<>();
//用一个ArrayList保存一组解
ArrayList<Integer> solution = new ArrayList<>();
//从0位置开始填充数
backtrack1(nums,result,solution,0);
return result;
}
//定义一个辅助集合,保存已经用过的数
HashSet<Integer> filled = new HashSet<>();
//实现一个回溯方法
public void backtrack1(int[] nums,List<List<Integer>> result,List<Integer> solution,int i){
int n = nums.length;
//首先,判断退出递归调用的场景
if(i>=n){
result.add(new ArrayList<>(solution));
}else {
//需要对i位置进行选数填入,需要遍历数组中所有数,取没有用过的数进行填充
for (int j = 0; j <n ; j++) {
if(!filled.contains(nums[j])){
//没用过直接填入
solution.add(nums[j]);
filled.add(nums[j]);
//递归调用,处理下一个位置
backtrack1(nums,result,solution,i+1);
//回溯,回退状态
solution.remove(i);
filled.remove(nums[j]);
}
}
}
}
//方法二:空间优化
public List<List<Integer>> permute(int[] nums) {
//定义保存结果的list
ArrayList<List<Integer>> result = new ArrayList<>();
//用一个ArrayList保存一组解
ArrayList<Integer> solution = new ArrayList<>();
//把nums复制到solution
for (int num : nums) {
solution.add(num);
}
//从0位置开始填充数
backtrack(result,solution,0);
return result;
}
public void backtrack(List<List<Integer>> result, List<Integer> solution, int i){
int n = solution.size();
// 首先判断退出递归调用的场景
if (i >= n){
result.add(new ArrayList<>(solution));
} else {
// 需要对i位置选数填入,遍历数组中所有数,取没有用过的数进行填充
for (int j = i; j < n; j++){
Collections.swap(solution, i, j);
// 递归调用,处理后面的位置
backtrack(result, solution, i + 1);
// 回溯
Collections.swap(solution, i, j);
}
}
}
public static void main(String[] args) {
int[] nums = {1,2,3};
Permutation permutation = new Permutation();
List<List<Integer>> result = permutation.permute(nums);
for (List<Integer> solution : result) {
for (Integer num : solution) {
System.out.print(num+"\t");
}
System.out.println();
}
}
}