题目
给定一个没有重复数字的序列,返回其所有可能的全排列。
示例:
输入: [1,2,3]
输出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
算法1
public class P46_Permutations {
List<List<Integer>> rlist = new ArrayList<>();
public List<List<Integer>> permute(int[] nums) {
if(nums==null||nums.length==0){
return rlist;
}
List<Integer> list = new ArrayList<>();
for(int i = 0;i<nums.length;i++){
list.add(nums[i]);
}
recursion(list,new ArrayList<>());
return rlist;
}
private void recursion(List<Integer> list,List<Integer> result){
if(list.size()==0){
rlist.add(result);
return;
}else {
for(int num : list){
List<Integer> nextList = new ArrayList<>();
List<Integer> nextresult = new ArrayList<>();
Integer n = num;
nextList.addAll(list);
nextList.remove(n);
nextresult.addAll(result);
nextresult.add(n);
recursion(nextList,nextresult);
}
}
}
}
思路:
- 将原先的nums[] 数组转换成list
- 每层递归对list中剩余的num遍历,这里遍历的目的是为了保证相同位置可以取到所有num,即达到了全排列的效果,循环内:
- 从nums中移除num
- 将num加入到新的序列nextresult中
- 进入下一层递归
- 若list中为空,则result即为全排列中的一个解
算法2
public class P46_Permutations2 {
public static void swap(int[] nums, int i, int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
/**
* 全排列函数
*
* @param nums
* @param p 起始位置
* @param q 结束位置(include)
*/
public void perm(int[] nums, int p, int q) {
if (p == q) {
List<Integer> values = new ArrayList<>();
for (int i = 0; i < nums.length; i++) {
values.add(nums[i]);
}
list.add(values);
}
for (int i = p; i <= q; i++) {
swap(nums, p, i);
perm(nums, p + 1, q);
swap(nums, p, i);
}
}
List<List<Integer>> list = new ArrayList<>();
public List<List<Integer>> permute(int[] nums) {
perm(nums, 0, nums.length - 1);
return list;
}
}
思路:leetcode高性能解法,咱们重点看他的递归思路。
- p和q分别为起始位置和结束位置
- 从p到q依次遍历,i为当前遍历的下标,循环内部为:
- 交换p和i
- p步进1,进入下一层递归
- 还原p和i,保证遍历到下一个i时,同层递归的nums数组是一样的
这里的递归通俗的理解就是:同一深度层次的递归将首部的p与之后的数依次做交换,交换完成进入下一层递归,最后还原p与其他数的交换,保证同层遍历p到q时,使用相同序列的nums数组。