一. 引例
1. 求数组的全排列
Leetcode 46: 给定一个 没有重复 数字的序列,返回其所有可能的全排列。
输入: [1,2,3]
输出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
以上图为例,初始的状态为空,我们首先将上述树看作一个多叉树,每次从左到右遍历,在叶子节点处得到最大长度的序列,实现代码如下,
# include
# include
# include
using namespace std;
class Solution {
public:
vector> results;
vector temp;
vector used;
void dfs(vector &nums, vector &used, int count) {
int len = nums.size();
// 递归终止条件
if (count == len) {
results.push_back(temp);
return;
}
for (int i = 0; i < len; i++) {
if (used[i])
continue;
temp.push_back(nums[i]);
used[i] = true;
count = count + 1;
dfs(nums, used, count);
temp.pop_back();
used[i] = false;
count = count - 1;
}
}
vector> permuteUnique(vector& nums) {
if (nums.size() == 0)
return results;
int len = nums.size();
for (int i = 0; i < len; i++) used.push_back(false);
dfs(nums, used, 0);
return results;
}
};
int main() {
Solution solution;
vector nums({1, 2, 3});
vector> results = solution.permuteUnique(nums);
for (int i = 0; i < results.size(); i++) {
for (int j = 0; j < results[i].size(); j++)
cout << results[i][j] << "\t";
cout << endl;
}
return 0;
}
2. 求重复数组的全排列
若数组中出现重复元素,则涉及到DFS的一个基本操作,剪枝,关键就在于如何选择剪枝的条件。
Leetcode 47: 给定一个可包含重复数字的序列,返回所有不重复的全排列。
输入: [1,1,2]
输出:
[
[1,1,2],
[1,2,1],
[2,1,1]
]
与无重复元素的全排列不同,此时多了一种特殊条件,当遍历到位置为 i 的节点( i > 0 )时,如果nums[i] == nums[i-1],并且nums[i-1]未遍历过,说明此时nums[i-1]在这次遍历中会出现在nums[i]之后,因此需要额外设置添加条件。
# include
# include
# include
using namespace std;
class Solution {
public:
vector> results;
vector temp;
vector used;
void dfs(vector &nums, vector &used, int count) {
int len = nums.size();
// 递归终止条件
if (count == len) {
results.push_back(temp);
return;
}
for (int i = 0; i < len; i++) {
if (used[i])
continue;
if (i > 0 && nums[i] == nums[i-1] && !used[i-1])
continue;
temp.push_back(nums[i]);
used[i] = true;
count = count + 1;
dfs(nums, used, count);
temp.pop_back();
used[i] = false;
count = count - 1;
}
}
vector> permuteUnique(vector& nums) {
if (nums.size() == 0)
return results;
sort(nums.begin(), nums.end());
int len = nums.size();
for (int i = 0; i < len; i++) used.push_back(false);
dfs(nums, used, 0);
return results;
}
};
int main() {
Solution solution;
vector nums({1, 1, 2, 2});
vector> results = solution.permuteUnique(nums);
for (int i = 0; i < results.size(); i++) {
for (int j = 0; j < results[i].size(); j++)
cout << results[i][j] << "\t";
cout << endl;
}
return 0;
}