[英]permutations algorithm
这是一个类,所以请不要太具体,但我正在寻找一种方法来列出数字数组的所有排列。
我们必须在不同的柱子(如锁)上排列不同的数字来解锁组合。 4 根柱子上的每根柱子上可能有 6 个数字。 但只要 n>r,它就应该适用于 r 上的任何 n。
我有办法随机生成一个组合,并有条不紊地在列表中查找它,但我无法生成生成所有排列的算法。
我能够在 C++ 中使用它获得数字 1-6 的所有组合:
//n = number of digits - 1; list = list of digits to work with;
//number=finalized list of digits
void permute(int n, vector<int> list, vector<vector<int>>* number)
{
if(n==1)
{
number->push_back(list);
}else
{
for(int i = 1;i<n;i++)
{
permute(n-1,list, number);
if(n%2 == 0)
{
swap(list[1],list[n]);
}else
{
swap(list[i],list[n]);
}
}
}
};
但是后来我得到了一个列表,例如 123456 163452 等,其中 1 始终是第一位数字,但我还需要在第一位数字切换并且只有 4 位数字出现时获取。
例子
6341
4163
等等,其中有 4 位数字,范围从 1 到 6,并且您有所有可能的组合。
谁能指出我正确的方向,让另一种算法补充这一点?
C++ 为此提供了一个完美的解决方案 - 它是std::next_permutation
(您需要包含<algorithms>
才能使用它)。
vector<int> list;
std::sort(list.begin(), list.end());
do {
// use the current permutation of the list
} while (std::next_permutation(list.begin(), list.end()));
关于此函数的重要一点是,如果您想遍历范围的所有排列,则必须在第一次调用next_permuration
之前对范围进行排序,否则您将在用完所有排列之前停止。
如果您需要自己实现,这可能没有帮助,但是 C++ 内置了next_permutation
。
http://www.cplusplus.com/reference/algorithm/next_permutation/
该函数背后的算法解释如下: std::next_permutation Implementation Explanation
从 N 项列表递归生成 N 长度排列的通用算法是:
对于列表中的每个元素 x
复制一个没有元素 x 的列表; 称之为 newList 查找 newList 的所有排列(这是递归,顺便说一句)
将元素 x 添加到 newList 的每个排列的开头
#include <iostream>
#include <list>
typedef std::list<int> IntList;
void iterlist(IntList& lst)
{
for (IntList::iterator it=lst.begin(); it!=lst.end(); it++)
cout << " " << *it;
cout << endl;
}
std::list<IntList> permute(IntList& L1)
{
if (L1.size() == 1)
return std::list<IntList>(1,L1);
std::list<IntList> res;
for (IntList::iterator i = L1.begin(); i != L1.end();)
{
// remember this
int x = (*i);
// make a list without the current element
IntList tmp(L1.begin(), i++);
tmp.insert(tmp.end(), i, L1.end());
// recurse to get all sub-permutations
std::list<IntList> sub = permute(tmp);
// amend sub-permutations by adding the element
for (std::list<IntList>::iterator j=sub.begin(); j!=sub.end();j++)
(*j).push_front(x);
// finally append modified results to our running collection.
res.insert(res.begin(), sub.begin(), sub.end());
}
return res;
}
int main()
{
IntList lst;
for (int i=0;i<4;i++)
lst.push_back(i);
std::list<IntList> res = permute(lst);
for (std::list<IntList>::iterator i=res.begin(); i!=res.end(); i++)
iterlist(*i);
return 0;
}
首先,让我们谈谈您的问题,打印集合 {1,2,3,4,5,6} 中的所有P(6,4)数组,但 std::next_permutation 仅适用于所有元素的排列( P(6,6) ),不适合您的问题( P(6,4) )。 我认为使用 std::next_permutation 可以很容易地得到组合,因为我们知道P(6,4)=C(6,4)*P(4,4)
,简单的代码实现可能是这样的:
1 #include <iostream>
2 #include <vector>
3
4 int main()
5 {
6 std::vector<int> list;
7 std::vector<int> subList;
8 std::vector<bool> flag;
9
10 for (int i=1; i<=6; ++i)
11 list.push_back(i);
12 flag.insert(flag.end(),4,1);
13 flag.insert(flag.end(),2,0);
14 std::sort(flag.begin(), flag.end());
15 do
16 {
17 subList.clear();
18 for(int i=0; i<flag.size(); ++i)
19 {
20 if(flag[i])
21 {
22 subList.push_back(list[i]);
23 }
24 }
25 do
26 {
27 for(std::vector<int>::iterator it=subList.begin(); it!=subList.end(); ++it)
28 {
29 std::cout << *it << " ";
30 }
31 std::cout << std::endl;
32 }while(std::next_permutation(subList.begin(), subList.end()));
33 std::cout << std::endl;
34 } while(std::next_permutation(flag.begin(), flag.end()));
35 return 0;
36 }
这显然是C(6,4)的外循环查找和P(4,4)的内循环查找。 没有花太多时间在你的代码上,对于组合,你可以像DFS一样使用搜索方法,参考:组合
此函数使用 bitset 列出所有排列
#include <iostream>
#include <string>
#include <bitset>
using namespace std;
const int N = 3;
void permute(string_view s, bitset<N> &mask, string &pref)
{
if (mask.all()) {
cout << pref << endl;
return;
}
for (int i = 0; i < N; i++) {
if (!mask[i]) {
mask.set(i);
pref.push_back(s[i]);
permute(s, mask, pref);
pref.pop_back();
mask.reset(i);
}
}
}
int main()
{
string pref;
bitset<N> mask;
permute(string("abc"), mask, pref);
return 0;
}
并进行一些修改后,它会打印所有组合
#include <iostream>
#include <string>
#include <bitset>
using namespace std;
const int N = 3;
const int M = 2;
void permute(string_view s, bitset<N> &mask, string &pref)
{
if (pref.size() == M) {
cout << pref << endl;
return;
}
for (int i = 0; i < N; i++) {
if (!mask[i]) {
mask.set(i);
permute(s, mask, pref);
pref.push_back(s[i]);
permute(s, mask, pref);
pref.pop_back();
mask.reset(i);
break;
}
}
}
int main()
{
string pref;
bitset<N> mask;
permute(string("abc"), mask, pref);
return 0;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.