LeetCode 46 题的题目描述为:给定一个不含重复数字的数组 nums ,返回其所有可能的全排列。你可以按任意顺序返回答案。
解题思路:
该题可以使用回溯算法来解决,回溯算法解决的问题都可以抽象成树结构,每个节点表示一个状态,每个节点的子节点表示在该状态下可以转移到的所有状态。
在本题中,我们可以将每个元素看作一个节点,然后每个节点的子节点是剩下的元素,表示选择了该元素后可以继续选择哪些元素。因此,我们可以使用回溯算法来遍历这棵树,找到所有的解。
具体实现时,我们可以使用一个数组来保存当前选择的元素,使用一个布尔数组来标每个元素是否已经被选择过,然后按照如下步骤进行回溯:
如果选择的元素数量等于原始数组的长度,说明已经选择了所有元素,将当前选择的元素列表加入最终结果中。
遍历原始数组,对于每个未被选择过的元素,将其加入选择列表中,并将其标记为已选择,然后递归进入下一层。
回溯时,将选择列表中最后一个元素删除,并将其标记为未选择。
重复上述步骤,直到遍历完所有状态。
Java 代码实现:
class Solution {
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
boolean[] used = new boolean[nums.length];
backtrack(nums, new ArrayList<>(), used, res);
return res;
}
private void backtrack(int[] nums, List<Integer> temp, boolean[] used, List<List<Integer>> res) {
if (temp.size() == nums.length) {
res.add(new ArrayList<>(temp));
return;
}
for (int i = 0; i < nums.length; i++) {
if (!used[i]) {
temp.add(nums[i]);
used[i] = true;
backtrack(nums, temp, used, res);
used[i] = false;
temp.remove(temp.size() - 1);
}
}
}
}
时间复杂度:O(n×n!),其中 n 表示数组的长度,n! 表示全排列的总数,因为每个全排列包含 n 个元素,因此总共需要枚举 n×n! 个状态。
空间复杂度:O(n),其中 n 表示数组的长度,空间复杂度取决于递归调用栈的深度和存储当前选择的元素的列表。在最坏情况下,递归调用栈的深度为 n ,因此空间复杂度为 O(n)。