文章目录
题目:
给定一个 没有重复 数字的序列,返回其所有可能的全排列。
示例:
输入: [1,2,3]
输出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
解法1:递归(换位)
/**
* 思路:
* 放格子,第一个格子放所有的数
* 第二个放除第一个格子外所有的数
* 第三个格子放除1,2格子中的所有的数
* 。。。
* 最后就是所有的可能性
*
* 为了实现上面的效果
* 我们把nums所有的数存入list,之后在其每个位置(格子)上进行交换
* 先和自身换,之后和后面所有的数进行交换。这样第一个格子就存储了所有的数
* 对于后面的格子用递归,进行同样的操作
* 最后要把变换后的数换回来,以便下次递归不重复
*/
public List<List<Integer>> permute(int[] nums) {
ArrayList<List<Integer>> result = new ArrayList<>();
ArrayList<Integer> list = new ArrayList<>();
for (int num:nums)list.add(num);
backtrack(nums.length,0,list,result);
return result;
}
private void backtrack(int length, int lattice, ArrayList<Integer> list, ArrayList<List<Integer>> result) {
if (lattice==length) {
result.add(new ArrayList<>(list));
return;
}
for (int i=lattice;i<length;i++){
Collections.swap(list,lattice,i);
backtrack(length,lattice+1,list,result);
Collections.swap(list,lattice,i);
}
}
时间复杂度:On^2
空间复杂度:On
解法2:
/**
* 和解法1的思路一样,不过这里借用了set
* 思路:
* 往格子里放数,当前格子的数需要遍历数组,并且不能是之前放过的
* 因为没有从重复数字用set来存放之前放过的数。
* 每次递归结束就从set和list中移除这个数
*/
public List<List<Integer>> permute(int[] nums) {
ArrayList<List<Integer>> result = new ArrayList<>();
LinkedList<Integer> list = new LinkedList<>();
HashSet<Integer> set = new HashSet<>();
recursive(nums,0,result,list,set);
return result;
}
private void recursive(int[] nums, int lattice, ArrayList<List<Integer>> result, LinkedList<Integer> list, HashSet<Integer> set) {
if (lattice==nums.length){
result.add(new ArrayList<>(list));
return;
}
for (int i:nums){
if (set.add(i)){
list.add(i);
recursive(nums,lattice+1,result,list,set);
list.removeLast();
set.remove(i);
}
}
}
时间复杂度:On^2
空间复杂度:On