全排列和组合本质都是DFS(Deapth First Search)
算法的思想。
-
目标
输出
1-3
的全排列和组合.输出结果:
-
程序
#include <iostream>
using namespace std;
// 组合
void dfs(int step, int goal, int cnt);
// 排列
void dfs(int goal, int step);
void dfs2(int step, int goal, int cnt);
int arr[100];
bool visited[100];
int main() {
memset(arr, 0, sizeof(arr));
std::cout << "Hello, World!" << std::endl;
dfs(0, 3, 0);
cout << "======" << endl;
memset(visited, 0, sizeof(visited));
dfs(3, 0);
return 0;
}
/**
* 组合: 1 - 3的组合
* @param step
* @param goal
* @param cnt
*/
void dfs(int step, int goal, int cnt){
if (step == goal) {
if (cnt == 0) {
cout << "null" << endl;
return;
}
for(int i = 0; i < cnt; i++) {
cout << arr[i] << " ";
}
cout << endl;
return;
}
dfs(step + 1, goal, cnt);
arr[cnt] = step + 1;
dfs(step + 1, goal, cnt + 1);
return;
}
/**
* 排列
* @param goal
* @param step
*/
void dfs(int goal, int step) {
if(step == goal) {
for (int i = 0; i < goal; i++) {
cout << arr[i] << " ";
}
cout << endl;
return;
}
for(int i = 0; i < goal; i++) {
if(visited[i]) {
continue;
}
visited[i] = true;
arr[step] = i + 1;
dfs(goal, step + 1);
visited[i] = false;
}
}
全排列
- Python
def dfs(nums, used, res):
if len(nums) == 0:
res.append(nums[:])
return
for i in range(len(nums)):
if not used[i]:
used[i] = True
dfs(nums[:i] + nums[i + 1:], used, res)
used[i] = False
def perm(nums):
res = []
used = [False] * len(nums)
dfs(nums, used, res)
return res
print(perm([1, 2, 3]))
输出:
[1, 2, 3]
[1, 3, 2]
[2, 1, 3]
[2, 3, 1]
[3, 1, 2]
[3, 2, 1]
- C++
#include <vector>
using namespace std;
void dfs(vector<int>& nums, vector<bool>& used, vector<vector<int>>& res) {
if (nums.empty()) {
res.push_back(nums);
return;
}
for (int i = 0; i < nums.size(); i++) {
if (!used[i]) {
used[i] = true;
dfs(nums, used, res);
used[i] = false;
}
}
}
vector<vector<int>> perm(vector<int>& nums) {
vector<vector<int>> res;
vector<bool> used(nums.size(), false);
dfs(nums, used, res);
return res;
}
int main() {
vector<int> nums = {1, 2, 3};
vector<vector<int>> res = perm(nums);
for (auto& v : res) {
for (auto& i : v) {
cout << i << " ";
}
cout << endl;
}
return 0;
}
组合
- Python
def dfs(nums, used, res, n, k):
if k == 0:
res.append(nums[:])
return
for i in range(n):
if not used[i]:
used[i] = True
dfs(nums[:i] + nums[i + 1:], used, res, n - 1, k - 1)
used[i] = False
def combine(nums, n, k):
res = []
used = [False] * n
dfs(nums, used, res, n, k)
return res
print(combine([1, 2, 3], 3, 2))
输出:
[1, 2]
[1, 3]
[2, 1]
[2, 3]
[3, 1]
[3, 2]
- C++
#include <vector>
using namespace std;
void dfs(vector<int>& nums, vector<bool>& used, vector<vector<int>>& res, int n, int k) {
if (k == 0) {
res.push_back(nums);
return;
}
for (int i = 0; i < n; i++) {
if (!used[i]) {
used[i] = true;
dfs(nums, used, res, n - 1, k - 1);
used[i] = false;
}
}
}
vector<vector<int>> combine(vector<int>& nums, int n, int k) {
vector<vector<int>> res;
vector<bool> used(n, false);
dfs(nums, used, res, n, k);
return res;
}
int main() {
vector<int> nums = {1, 2, 3};
vector<vector<int>> res = combine(nums, 3, 2);
for (auto& v : res) {
for (auto& i : v) {
cout << i << " ";
}
cout << endl;
}
return 0;
}
算法说明
-
全排列
全排列是指将给定的一个数字列表按照字典序排列,所有可能的排列。
算法思路:
- 从第一个数字开始,依次选择数字放入排列中。
- 当选择了第 i 个数字后,需要将剩下的 (n - i) 个数字进行排列。
- 重复步骤 2,直到所有数字都选择完毕。
-
组合
组合是指从 n 个元素中选择 k 个元素,所有可能的组合。
算法思路:
- 从第一个数字开始,依次选择数字放入组合中。
- 当选择了第 i 个数字后,需要将剩下的 (n - i) 个元素进行组合。
- 重复步骤 2,直到选择了 k 个数字。
注意:在组合问题中,需要注意数字的顺序不重要。因此,在回溯过程中,需要将选择过的数字恢复。