1. 题目
2. 分析
题目要求我们给出所有的排列方式,首先我们知道,如果是排列的那话,那么我们每一个数字都只能使用一次,如图的三个数字:
- 首先我们拿出1,剩下 2 和 3
1.1 再接着找下一个没用到的数组,就是2:
1.1.1 此时,排列只有两个,我们继续找到下一个3,这样子我们就得到了第一个组合1,2,3
1.2 拿到1之后,我们不拿2了,而是拿3
1.2.1 然后我们再拿一个2,就得到了第二个组合1,3,2
2.1 这次我们第一个不拿1,而是拿2,以此类推,我们最终拿到的组合如下:
[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
我们上面的过程,可以用递归+回溯进行实现:
- 每一次递归都找一个没使用过的数字,数量够了结束递归。
- 每次选中的数字,我们将他标记为已使用后进行递归,递归结束之后重新标记为未使用。
3. 代码
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> lists = new ArrayList<>();
List<Integer> list = new ArrayList<>();
int[] used = new int[nums.length];
permuteSub(nums, lists, list, used, 0);
return lists;
}
public void permuteSub(int[] nums, List<List<Integer>> lists, List<Integer> list, int[] used, int c) {
//排列数量够了,结束递归
if (c == nums.length) {
//注意这个要new 一个list
lists.add(new ArrayList<>(list));
return;
}
for (int i = 0; i < nums.length; i++) {
if (used[i] == 0) {
used[i] = 1;
list.add(nums[i]);
permuteSub(nums, lists, list, used, c+1);
//通过remove,递归过程中使用同一个list,减少空间消耗
list.remove(list.size() - 1);
used[i] = 0;
}
}
}