今天做了一个算法题,题目大概是这样的:
已知: n个数字序列,每个序列中包含m个数字,求这n个序列数字的所有可能的排列组合
给出一个例子,这个例子n是3,要求n可以是任意的。
input = {{1,2,3},
{4,5},
{6,7,8}}
output = {
{1,4,6},{1,4,7},{1,4,8},
{1,5,6},{1,5,7},{1,5,8},
{2,4,6},{2,4,7},{2,4,8},
{2,5,6},{2,5,7},{2,5,8},
{3,4,6},{3,4,7},{3,4,8},
{3,5,6},{3,5,7},{3,5,8}}
不难看出
1.组合的总个数(total)为每一行数据个数的乘积。本题为3 × 2 × 3 = 18个(没剔除重复)。
2.每个组合内部数据的个数是输入数组的行数。本题是3行,一个组合内部是由3个数字组成。
3.每个组合内部的数据是每行取一个。
思路:
1.外循环控制组合的总个数,内循环控制每个组合内部数据的个数。
2.用vector< int> out 表示一个组合数据。
3.本题18个组合与其下标如下图所示:
可以看出第3行每遍历1个都会更换数字,第2行每3个更换数字,第1行每6个更换数字。我暂时把遍历x个后就更换数字,这个x叫做这一行的步长step。
步长step求法:
// 计算步长
int a = total;
for (int i = 0; i <inputSize.size(); ++i) {
a = a / inputSize[i];
step.push_back(a);
}
4.遍历数据,每一行各去一个数据,取该行某数据下标为:i / 该行的步长 % 该行的数据个数。其中i是组合总数的下标。
for (int i = 0; i < total; ++i) {
for (int j = 0; j < inputSize.size(); j++) {
out.push_back(input.at(j).at(i / step[j] % inputSize[j]));
}
output->push_back(out); // 添加一个组合数据
out.clear();
}
5.这里没考虑重复的情况,也没考虑各种非正常数据的情况。
总代码如下:
// 创建输入数组
void CreateInputData(vector<vector<int>> &input)
{
vector<int> n1;
n1.push_back(1);
n1.push_back(2);
n1.push_back(3);
input.push_back(n1);
vector<int> n2;
n2.push_back(4);
n2.push_back(5);
input.push_back(n2);
vector<int> n3;
n3.push_back(6);
n3.push_back(7);
n3.push_back(8);
input.push_back(n3);
}
// 打印函数
void PrintResult(vector<vector<int> >& result, int s)
{
int line = 0;
cout << "{";
for (auto i = result.begin(); i != result.end(); ++i) {
if ( line++%s == 0) {
cout << "\n ";
}
cout << "{";
for (auto j = i->begin(); j != i->end(); ++j) {
cout << *j << ",";
}
cout << "},";
}
cout << "\n}\n";
}
// 组合数据
void Combine(const vector<vector<int>>& input, vector<vector<int> >* output)
{
// 此处答题:
vector<int> out; // 用于存放一个组合
vector<int> inputSize; // 存放每一组数据大小
vector<int> step;
int total; // 组合的个数
// 计算每一组输入数据大小
for (int i = 0; i < input.size(); ++i) {
inputSize.push_back(input.at(i).size());
}
// 计算组合个数
for (int i = 0; i < inputSize.size(); ++i) {
total *= inputSize[i];
}
// 计算步长
int a = total;
for (int i = 0; i <inputSize.size(); ++i) {
a = a / inputSize[i];
step.push_back(a);
}
// 输出
for (int i = 0; i < total; ++i) {
for (int j = 0; j < inputSize.size(); j++) {
out.push_back(input.at(j).at(i / step[j] % inputSize[j]));
}
output->push_back(out);
out.clear();
}
}
int main()
{
vector<vector<int>> input;
vector<vector<int>> output;
CreateInputData(input);
Combine(input, &output);
PrintResult(output, input.size());
system("pause");
return 0;
}
总结:好久没做算法题了,突然一做简直要疯掉了,脑袋各种转不过来(本来就比较菜),在网上搜也搜不到,自己想也就只能想到这种方法了。如果哪位小伙伴有好方法可以分享出来。