题目名称:全排列
给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。
示例 1:
输入: nums = [1,2,3]
输出: [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
示例 2:
输入: nums = [0,1]
输出: [[0,1],[1,0]]
示例 3:
输入: nums = [1]
输出: [[1]]
提示:
1 <= nums.length <= 6-10 <= nums[i] <= 10nums中的所有整数 互不相同
思路分析
回溯就是不断抉择再撤销决策,再讲这两个大动作交给递归函数去做 和一般的递归一样,首先去明确递归函数需要做的是什么:
判断当前结果是否满足条件,若满足则将其加入结果list并返回 针对所有可选择的数,进入循环开始选择 判读当前数是否已经选过 若没选过,加入path并将新path带入下个递归 撤销选择,进入下一次循环
根据排列组合的性质进行解题,假设 List<List> subList为已求出的前n个数字的所有排列组合,那么里面的每个组合的list长度为n; 则当第n+1个数字(设为current)))加入的时候,此时的排列组合就是尝试将current加入到之前已有组合的0-n的位置,这样每个新生成的组合都是加入current之后的排列组合。
对于已有组合[1,2],当加入3的时候
- 首先,将3放置在第0位,也就是[1,2]的前面,生成新的组合[3,1,2];
- 其次,将3放置在第1位,也就是[1,2]的中间,生成新的组合[1,3,2];
- 之后,将3放置在第2位,也就是[1,2]的后面,生成新的组合[1,2,3]。
- 这样,对于已有组合[1,2]和3组成的新组合就获取到了,为[3,1,2],[1,3,2],[1,2,3];
对于每个已有的组合,将新加入的元素依次加入到组合的0-n位,这样,就能获取到全部的新组合。
Code实现
public List < List < Integer >> permute(int[] nums) {
if (nums == null || nums.length == 0) {
return new ArrayList < > ();
}
numbers = nums;
return helper(nums.length - 1);
}
private int[] numbers;
private List < List < Integer >> helper(int index) {
if (index == 0) {
// index为0,那么此时的组合只有第一位数字
List < Integer > list = Collections.singletonList(numbers[0]);
return Collections.singletonList(list);
}
// 获取已有组合
List < List < Integer >> subList = helper(index - 1);
// 当前待加入的数字
int currentNum = numbers[index];
List < List < Integer >> ans = new ArrayList < > ();
for (int i = 0; i <= index; i++) {
for (List < Integer > currentSub: subList) {
// 对于每个已有组合,将待加入数字插入到第i位,生成新的组合
List < Integer > current = new ArrayList < > (currentSub.subList(0, i));
current.add(currentNum);
current.addAll(currentSub.subList(i, index));
ans.add(current);
}
}
return ans;
}
结果
算法复杂度分析
- 时间复杂度:
- 空间复杂度: