梦想不会自己发光,真正闪耀的是那个为梦狂奔的你。献给知行的孩子们!(Eric.He著)
枚举算法是解决简单组合、排列问题的首选方案(数据规模小),核心是通过有序遍历所有可能的组合 / 排列候选,再筛选符合条件的结果。
以下是 6 个典型实例,覆盖无重复组合、有重复组合、全排列、部分排列等常见场景。
问题描述:
算法解析:
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> nums = {1, 2, 3};
cout << "[" << 1 << "," << 2 << "," << 3 << "]的所有全排列:" << endl;
// 三重循环枚举所有排列,确保元素不重复
int n = nums.size();
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
if (j == i) continue; // 避免重复选取同一个元素
for (int k = 0; k < n; ++k) {
if (k == i || k == j) continue; // 避免重复选取同一个元素
cout << "{" << nums[i] << ", " << nums[j] << ", " << nums[k] << "}" << endl;
}
}
}
return 0;
}
[1,2,3]的所有全排列:
{1, 2, 3}
{1, 3, 2}
{2, 1, 3}
{2, 3, 1}
{3, 1, 2}
{3, 2, 1}
问题描述:
算法解析:
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> nums = {1, 2, 3, 4};
int k = 2; // 选取2个元素
cout << "从[" << 1 << "," << 2 << "," << 3 << "," << 4 << "]中选取" << k << "个的所有排列:" << endl;
// 枚举所有部分排列(i ≠ j 确保不重复且考虑顺序)
int n = nums.size();
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
if (i == j) continue; // 避免重复选取同一个元素
cout << "{" << nums[i] << ", " << nums[j] << "}" << endl;
}
}
return 0;
}
从[1,2,3,4]中选取2个的所有排列:
{1, 2}
{1, 3}
{1, 4}
{2, 1}
{2, 3}
{2, 4}
...(后续省略)
问题描述:
算法解析:
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> nums = {1, 2, 3, 4};
int k = 2; // 选取2个元素
cout << "从[" << 1 << "," << 2 << "," << 3 << "," << 4 << "]中选取" << k << "个的所有组合:" << endl;
// 枚举所有无重复组合(i < j 避免重复)
int n = nums.size();
for (int i = 0; i < n; ++i) {
for (int j = i + 1; j < n; ++j) {
cout << "{" << nums[i] << ", " << nums[j] << "}" << endl;
}
}
return 0;
}
从[1,2,3,4]中选取2个的所有组合:
{1, 2}
{1, 3}
{1, 4}
{2, 3}
{2, 4}
{3, 4}
问题描述:
算法解析:
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> nums = {1, 2, 3};
int k = 2; // 选取2个元素
cout << "从[" << 1 << "," << 2 << "," << 3 << "]中选取" << k << "个的可重复组合:" << endl;
// 枚举所有可重复组合(i ≤ j 允许重复且避免顺序差异)
int n = nums.size();
for (int i = 0; i < n; ++i) {
for (int j = i; j < n; ++j) {
cout << "{" << nums[i] << ", " << nums[j] << "}" << endl;
}
}
return 0;
}
从[1,2,3]中选取2个的可重复组合:
{1, 1}
{1, 2}
{1, 3}
{2, 2}
{2, 3}
{3, 3}
问题描述:
算法解析:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main() {
vector<char> chars = {'a', 'b', 'c'};
int len = 2; // 组合长度
cout << "从{'a','b','c'}中生成长度为" << len << "的可重复字符组合:" << endl;
// 枚举所有字符组合
int n = chars.size();
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
string combo;
combo += chars[i];
combo += chars[j];
cout << "\"" << combo << "\"" << endl;
}
}
return 0;
}
从{'a','b','c'}中生成长度为2的可重复字符组合:
"aa"
"ab"
"ac"
"ba"
"bb"
"bc"
"ca"
"cb"
"cc"
问题描述:
算法解析:
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> nums = {1, 2, 3, 4, 5};
int k = 2; // 选取2个元素
int targetSum = 6; // 目标和
cout << "从[" << 1 << "," << 2 << "," << 3 << "," << 4 << "," << 5 << "]中选取" << k << "个和为" << targetSum << "的组合:" << endl;
// 枚举无重复组合,筛选和为目标值的结果
int n = nums.size();
for (int i = 0; i < n; ++i) {
for (int j = i + 1; j < n; ++j) {
if (nums[i] + nums[j] == targetSum) {
cout << "{" << nums[i] << ", " << nums[j] << "}" << endl;
}
}
}
return 0;
}
从[1,2,3,4,5]中选取2个和为6的组合:
{1, 5}
{2, 4}
枚举算法解决简单组合 / 排列问题的共性特点:
上述实例覆盖了数值、字符、带条件等常见场景,适合入门者理解组合 / 排列的本质及枚举算法的应用。