30、全排列
题目
30.0、回溯法
直接枚举所有可能,在递归的的时候通过哈希集合来判断,该数是否已经使用
public:
vector<vector<int>> permute0(vector<int>& nums)
{
vector<vector<int>> result;
unordered_set<int> data;
vector<int> temp;
depth(result, data, temp, nums);
return result;
}
private:
void depth(vector<vector<int>>& result, unordered_set<int>& data, vector<int>& temp, vector<int>& nums)
{
if (temp.size() == nums.size())
{
result.push_back(temp);
return;
}
for (auto& i : nums)
{
if (!data.count(i))
{
temp.push_back(i);
data.insert(i);
depth(result, data, temp, nums);
temp.pop_back();
data.erase(i);
}
}
}
时间复杂度:O(n^n)好家伙直接遍历了n的n次方遍
空间复杂度:O(n)递归n层的消耗,哈希集合的消耗,临时数组的消耗
30.1、回溯法优化
把递归每一层的作用定义如下
对于序列【1,2,3,4,5】
2与1交换,后面的【1,3,4,5】交由下一层完成
3与1交换,后面的【2,1,4,5】交由下一层完成
。。。。。。
规避了全枚举的问题和哈希集合
public:
//回溯法优化(取消使用哈希集合来判断是否已经使用该数)
vector<vector<int>> permute1(vector<int>& nums)
{
vector<vector<int>> result;
depth2(result, nums, 0);
return result;
}
private:
void depth2(vector<vector<int>>& result, vector<int>& nums, int index)
{
if (index == nums.size())result.push_back(nums);
for (int i = index; i < (int)nums.size(); i++)
{
swap(nums[i], nums[index]);//交换起始值与当前值的位置
depth2(result, nums, index + 1);
swap(nums[i], nums[index]);//撤销交换
}
}
时间复杂度:O(n!)这是答案的数量
空间复杂度:O(n)需要递归n层