Python 如何在c++;对小于总长度的位置数使用STL
我有一个带有Python 如何在c++;对小于总长度的位置数使用STL,python,c++,permutation,Python,C++,Permutation,我有一个带有std::pair对象的c++向量。我试图使用std::next\u permutation()生成向量对象的置换。但是,我希望排列具有给定的大小,您知道,类似于python中的permutations函数,其中指定了预期返回的排列的大小 基本上,c++相当于 import itertools list = [1,2,3,4,5,6,7] for permutation in itertools.permutations(list, 3): print(permutatio
std::pair
对象的c++向量。我试图使用std::next\u permutation()
生成向量对象的置换。但是,我希望排列具有给定的大小,您知道,类似于python中的permutations
函数,其中指定了预期返回的排列的大小
基本上,c++
相当于
import itertools
list = [1,2,3,4,5,6,7]
for permutation in itertools.permutations(list, 3):
print(permutation)
如果效率不是主要考虑的问题,我们可以迭代所有排列,跳过那些后缀不同的排列,只选择每个(N-k)代码>-第1个。例如,对于N=4,k=2
,我们有排列:
12 34 <
12 43
13 24 <
13 42
14 23 <
14 32
21 34 <
21 43
23 14 <
23 41
24 13 <
24 31
...
输出:
12 13 14 21 23 24 31 32 34 41 42 43
您可以使用两个循环:
- 取每个n元组
- 迭代n元组的置换
模板
空位置换(F,std::vector v,std::size\u t n)
{
std::向量bs(v.size()-n,false);
调整大小(v.size(),真);
排序(v.begin(),v.end());
做{
std::向量子;
对于(std::size_t i=0;i!=bs.size();++i){
如果(bs[i]){
sub.push_back(v[i]);
}
}
做{
f(小组委员会);
}
while(std::next_置换(sub.begin(),sub.end());
}while(std::next_置换(bs.begin(),bs.end());
}
这里有一个有效的算法,它不直接使用std::next_排列,而是利用该函数的工作机制。也就是说,std::swap
和std::reverse
。另外,这是一个好主意
这是来自的可运行代码,这是我经过深思熟虑后的解决方案
#include <algorithm>
#include <iostream>
#include <set>
#include <vector>
int main() {
std::vector<int> job_list;
std::set<std::vector<int>> permutations;
for (unsigned long i = 0; i < 7; i++) {
int job;
std::cin >> job;
job_list.push_back(job);
}
std::sort(job_list.begin(), job_list.end());
std::vector<int> original_permutation = job_list;
do {
std::next_permutation(job_list.begin(), job_list.end());
permutations.insert(std::vector<int>(job_list.begin(), job_list.begin() + 3));
} while (job_list != original_permutation);
for (auto& permutation : permutations) {
for (auto& pair : permutation) {
std::cout << pair << " ";
}
std::endl(std::cout);
}
return 0;
}
#包括
#包括
#包括
#包括
int main(){
std::矢量作业列表;
std::集合置换;
for(无符号长i=0;i<7;i++){
国际工作;
std::cin>>工作;
作业列表。推回(作业);
}
排序(job_list.begin(),job_list.end());
std::向量原始排列=作业列表;
做{
std::next_排列(job_list.begin(),job_list.end());
insert(std::vector(job_list.begin(),job_list.begin()+3));
}while(作业列表!=原始排列);
用于(自动置换和置换:置换){
用于(自动配对:置换(&P){
std::cout使用迭代器接口打开Joseph Wood答案,您可能有一个类似于std::next\u permutation的方法:
template <typename IT>
bool next_partial_permutation(IT beg, IT mid, IT end) {
if (beg == mid) { return false; }
if (mid == end) { return std::next_permutation(beg, end); }
auto p1 = mid;
while (p1 != end && !(*(mid - 1) < *p1))
++p1;
if (p1 != end) {
std::swap(*p1, *(mid - 1));
return true;
} else {
std::reverse(mid, end);
auto p3 = std::make_reverse_iterator(mid);
while (p3 != std::make_reverse_iterator(beg) && !(*p3 < *(p3 - 1)))
++p3;
if (p3 == std::make_reverse_iterator(beg)) {
std::reverse(beg, end);
return false;
}
auto p2 = end - 1;
while (!(*p3 < *p2))
--p2;
std::swap(*p3, *p2);
std::reverse(p3.base(), end);
return true;
}
}
模板
bool next\u partial\u置换(它是beg,它是mid,它是end){
如果(beg==mid){return false;}
if(mid==end){return std::next_置换(beg,end);}
自动p1=mid;
而(p1!=结束(*(中间-1)<*p1))
++p1;
如果(p1!=结束){
标准:掉期(*p1,*(mid-1));
返回true;
}否则{
标准:反向(中间、末端);
自动p3=std::生成反向迭代器(mid);
while(p3!=std::make_reverse_iterator(beg)&&!(*p3<*(p3-1)))
++p3;
if(p3==std::make_reverse_迭代器(beg)){
标准::反向(beg,end);
返回false;
}
自动p2=结束-1;
而(!(*p3<*p2))
--p2;
标准:互换(*p3,*p2);
std::reverse(p3.base(),end);
返回true;
}
}
这段代码的时间复杂度是多少?平均情况下是O(places_required*n),最坏情况下是O(n^2)?我也在猜测最佳情况下是O(n),即1place@d4rk4ng31:我们确实只遇到一次置换。置换的复杂性是“不清楚”的,因为它计算交换(线性)子向量的提取可以改进,但我不认为它会改变复杂度。此外,置换的数量取决于向量大小,所以2个参数不是独立的。不应该是“代码> STD::vector和v< /Cord>?@ L.F:它是有目的的。我认为我不需要改变调用方的值(我现在排序“代码> V< /代码>”)。。我可能通过常量引用传递,并在正文中创建一个排序副本。@Jarod42哦,对不起,我完全误读了代码。是的,在这里通过值传递是正确的。作为旁注,您希望如何处理重复输入,因为(1,1)
?python排列提供了重复的[(1,1),(1,1)]
,而std::next_permution
避免重复(仅{1,1}
)。与我的答案不同,它更等同于Evg的答案(但Evg更有效地跳过重复)。permute
实际上只能设置。插入(vec)
删除一个大因素。我会说O(nb_total_perm*log(nb_res))
(nb\u total\u perm
主要是阶乘(job\u list.size())
和nb\u res
结果大小:permutations.size()
),所以还是太大了。(但现在你处理重复的输入与Evg相反),你甚至可以用签名bool nextPartialPermutation(它开始,它中间,它结束)
@Jarod42,这是一个非常好的解决方案。你应该把它作为一个答案添加进去……我最初的想法是改进你的答案,但没问题,添加了。
template <typename F, typename T>
void permutation(F f, std::vector<T> v, std::size_t n)
{
std::vector<bool> bs(v.size() - n, false);
bs.resize(v.size(), true);
std::sort(v.begin(), v.end());
do {
std::vector<T> sub;
for (std::size_t i = 0; i != bs.size(); ++i) {
if (bs[i]) {
sub.push_back(v[i]);
}
}
do {
f(sub);
}
while (std::next_permutation(sub.begin(), sub.end()));
} while (std::next_permutation(bs.begin(), bs.end()));
}
#include <iostream>
#include <vector>
#include <algorithm>
void nextPartialPerm(std::vector<int> &z, int n1, int m1) {
int p1 = m1 + 1;
while (p1 <= n1 && z[m1] >= z[p1])
++p1;
if (p1 <= n1) {
std::swap(z[p1], z[m1]);
} else {
std::reverse(z.begin() + m1 + 1, z.end());
p1 = m1;
while (z[p1 + 1] <= z[p1])
--p1;
int p2 = n1;
while (z[p2] <= z[p1])
--p2;
std::swap(z[p1], z[p2]);
std::reverse(z.begin() + p1 + 1, z.end());
}
}
int main() {
std::vector<int> z = {1, 2, 3, 4, 5, 6, 7};
int m = 3;
int n = z.size();
const int nMinusK = n - m;
int numPerms = 1;
for (int i = n; i > nMinusK; --i)
numPerms *= i;
--numPerms;
for (int i = 0; i < numPerms; ++i) {
for (int j = 0; j < m; ++j)
std::cout << z[j] << ' ';
std::cout << std::endl;
nextPartialPerm(z, n - 1, m - 1);
}
// Print last permutation
for (int j = 0; j < m; ++j)
std::cout << z[j] << ' ';
std::cout << std::endl;
return 0;
}
1 2 3
1 2 4
1 2 5
1 2 6
1 2 7
.
.
.
7 5 6
7 6 1
7 6 2
7 6 3
7 6 4
7 6 5
#include <algorithm>
#include <iostream>
#include <set>
#include <vector>
int main() {
std::vector<int> job_list;
std::set<std::vector<int>> permutations;
for (unsigned long i = 0; i < 7; i++) {
int job;
std::cin >> job;
job_list.push_back(job);
}
std::sort(job_list.begin(), job_list.end());
std::vector<int> original_permutation = job_list;
do {
std::next_permutation(job_list.begin(), job_list.end());
permutations.insert(std::vector<int>(job_list.begin(), job_list.begin() + 3));
} while (job_list != original_permutation);
for (auto& permutation : permutations) {
for (auto& pair : permutation) {
std::cout << pair << " ";
}
std::endl(std::cout);
}
return 0;
}
template <typename IT>
bool next_partial_permutation(IT beg, IT mid, IT end) {
if (beg == mid) { return false; }
if (mid == end) { return std::next_permutation(beg, end); }
auto p1 = mid;
while (p1 != end && !(*(mid - 1) < *p1))
++p1;
if (p1 != end) {
std::swap(*p1, *(mid - 1));
return true;
} else {
std::reverse(mid, end);
auto p3 = std::make_reverse_iterator(mid);
while (p3 != std::make_reverse_iterator(beg) && !(*p3 < *(p3 - 1)))
++p3;
if (p3 == std::make_reverse_iterator(beg)) {
std::reverse(beg, end);
return false;
}
auto p2 = end - 1;
while (!(*p3 < *p2))
--p2;
std::swap(*p3, *p2);
std::reverse(p3.base(), end);
return true;
}
}