这是我参与2022首次更文挑战的第15天,活动详情查看:2022首次更文挑战
leetcode 全排列
给定一个不含重复数字的数组 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]]
解题:
这个相当于密码锁上有几个数字,让你猜这个密码有可能是什么,但是这些数组每个组合只能使用一次,那么可以看成这些组合都是待填的空格,你只需把这些数组按不同的排列组合依次填上去即可。那么这就是一种穷举的算法了,我们从左到右依次将数字填入,最后填完数字就是一种组合,当然这些组合不能重复存在。具体的可以利用递归来实现,可以将给定的数组分成两个部分,一部分表示为填过使用了的数字,一部分表示还未使用待填的数字,然后递归的时候动态维护这个数组就行。 假如我们填到了first这个位置,那么数组中first的前面部分是已经填过了的,first后面的就是待填的数,然后就是用first后面的数字去填first位置的数了,那么填过去这个数后,我们就将这个数和第first个数交换,使得再填first的下一个数的时候,数组的first前的数是填过了的,first+1后的数是待填的,然后回溯的时候只需要交换回来就可以回到上一步了。例如[2, 5, 8, 9, 10],需要填入第三个数了,已经填了[2, 5]两个数,那目前的数组就是[2, 5 | 8, 9, 10],|分隔符是区分两个部分的, 假如下一个位置是要填的是10,那么可以将2和10交换,变为[2, 5, 10 | 9, 8],使得数组保持分隔,左边的数已经填完,右边的数是待填的。
class Solution {
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> res = new ArrayList<List<Integer>>();
List<Integer> output = new ArrayList<Integer>();
for (int num : nums) {
output.add(num);
}
int n = nums.length;
backtrack(n, output, res, 0);
return res;
}
public void backtrack(int n, List<Integer> output, List<List<Integer>> res, int first) {
if (first == n) {
res.add(new ArrayList<Integer>(output));
}
for (int i = first; i < n; i++) {
Collections.swap(output, first, i);
backtrack(n, output, res, first + 1);
Collections.swap(output, first, i);
}
}
}