此题,一开始我使用了DFS和回溯,使用一个数组来记录使用过哪些元素,代码如下。另外需要注意此题nums中的元素,没有重复。
class Solution {
private:
void helper(vector<int>& nums, vector<bool>& ifUsed, vector<int>& item, vector<vector<int>>& res) {
if (item.size() == nums.size()) {
res.push_back(item);
return;
}
for (int i=0; i<nums.size(); i++) {
if (!ifUsed[i]) {
ifUsed[i] = true;
item.push_back(nums[i]);
helper(nums, ifUsed, item, res);
ifUsed[i] = false;
item.pop_back();
}
}
}
public:
vector<vector<int>> permute(vector<int>& nums) {
int len = (int)nums.size();
vector<int> item;
vector<bool> ifUsed (len, false);
vector<vector<int>> res;
helper(nums, ifUsed, item, res);
return res;
}
};
后来看了一下别人的做法,发现还可以使用插入法来解决本题。示例如下:
[1] [2, 1] [1, 2] [3, 2, 1] [2, 3, 1] [2, 1, 3] [3, 1, 2] [1, 3, 2] [1, 2, 3]需要注意的一点是,在遍历数组nums之前,需要向nums加入一个空vector,否则第一个元素将没有地方可以插入。代码如下:
class Solution {
public:
vector<vector<int>> permute(vector<int>& nums) {
vector<vector<int>> result;
vector<int> item;
result.push_back(item); // 加入空的vector
for (int i = 0; i < nums.size(); i++) {
// current用于存储每次遍历之后的结果
vector<vector<int>> current;
for (int j=0; j<result.size(); j++) {
// 共有result[j].size()+1个位置可以插入
for (int k = 0; k < result[j].size()+1; k++) {
// 把nums[i]插入到不同的位置
result[j].insert(result[j].begin()+k, nums[i]);
vector<int> tmp(result[j]);
current.push_back(tmp);
// 删除刚才在k下标位置插入的元素
result[j].erase(result[j].begin()+k);
}
}
result = current;
}
return result;
}
};
还有一种方法是利用交换法,通过每个元素和它后面的元素进行交换来解决这个问题,示例如下:
[1, 2, 3] [1, 3, 2] [2, 1, 3] [2, 3, 1] [3, 2, 1] [3, 1, 2]需要注意交换的算法逻辑及细节,代码如下:
class Solution {
private:
void helper(vector<int>& nums, int start, vector<vector<int>>& res) {
if (start >= nums.size()) {
res.push_back(nums);
return;
}
for (int j = start; j <= nums.size()- 1; j++) {
swap(nums[start], nums[j]);
helper(nums, start + 1, res);
swap(nums[start], nums[j]);
}
}
public:
vector<vector<int>> permute(vector<int>& nums) {
vector<vector<int>> res;
helper(nums, 0, res);
return res;
}
};