题目
给定一个不含重复数字的数组 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]]
分析
回溯算法是一种通过尝试所有可能的组合来解决问题的方法,对于全排列问题,它会递归地生成所有可能的排列。
回溯法
使用一个标记数组记录每个数字是否已被使用,当当前构建的排列长度等于数组长度时,将其确定为一个全排列并加入结果数组。在递归过程中,遍历数组中的每个数字,若该数字未被使用,则将其加入当前排列并标记为已使用,接着递归构建下一个位置的排列,完成递归后进行回溯,即撤销该数字的使用标记并从当前排列中移除,继续尝试其他数字,以此穷举所有可能的全排列组合。
时间复杂度:O(),其中
为数组的长度
空间复杂度:O()
cpp
class Solution {
public:
std::vector<std::vector<int>> permute(std::vector<int>& nums) {
std::vector<std::vector<int>> result;
std::vector<int> current;
std::vector<bool> used(nums.size(), false);
backtrack(nums, used, current, result);
return result;
}
private:
void backtrack(const std::vector<int>& nums, std::vector<bool>& used, std::vector<int>& current, std::vector<std::vector<int>>& result) {
// 如果当前排列的长度等于数组的长度,说明已经生成了一个全排列
if (current.size() == nums.size()) {
result.push_back(current);
return;
}
for (int i = 0; i < nums.size(); ++i) {
// 如果该数字已经在当前排列中使用过,则跳过
if (used[i]) continue;
// 选择当前数字
used[i] = true;
current.push_back(nums[i]);
// 递归生成下一个位置的排列
backtrack(nums, used, current, result);
// 回溯,撤销选择
used[i] = false;
current.pop_back();
}
}
};