Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/145.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/ant/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何在c++;对小于总长度的位置数使用STL_Python_C++_Permutation - Fatal编程技术网

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;
    }
}