题目
给定一个不含重复数字的数组 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] <= 10
nums 中的所有整数 互不相同
思路:回溯法
本题可以用回溯法求解。回溯法是一种通过探索所有可能的候选解来找出所有的解的算法。如果候选解被确认不是一个解的话(或者至少不是最后一个解),回溯算法会通过在上一步进行一些变化把这个候选解排除掉。 具体实现上,可以通过递归找到所有可能的排列。每次递归中,从未使用的数字中选取一个数字,将其加入到当前排列的末尾,然后递归下一层。当排列中的数字数量达到原序列长度时,就找到了一个排列。如果当前排列的数字数量小于原序列长度,继续递归寻找下一个数字。
function permute(nums: number[]): number[][] {
const len = nums.length;
const result = [];
const used = new Array(len).fill(false);
// 回溯法
const backtrack = (path: number[]) => {
// 符合条件
if(path.length === len) {
result.push(path.slice());
return;
}
// 挨个组合
for(let i = 0; i < len; i++) {
// 组合过的
if(used[i]) continue;
// 装进去
used[i] = true;
path.push(nums[i]);
// 进行递归
backtrack(path)
// 吐出来
used[i] = false;
path.pop();
}
}
backtrack([]);
return result;
};
总结
- 时间复杂度:,其中 为原序列长度。其中 为全排列的数量,需要遍历所有可能的排列,时间复杂度为 。而在每个排列中,需要遍历原序列中所有未使用的数字,时间复杂度为 ,因此总时间复杂度为 。
- 空间复杂度:,其中 为原序列长度。递归调用
backtrack函数时,需要使用 的栈空间存储当前排列。同时,还需要使用 的空间记录原序列中的数字是否已经在当前排列中使用过。因此总空间复杂度为 。 - 总结 本题是一道比较经典的回溯算法题目,对于初学者来说可以帮助他们更好地理解回溯算法。本题的解法可以应用到其他需要求解所有可能组合的题目中。