为什么这段代码没有产生所有的排列?

时间:2018-02-05 09:14:10

标签: c++ permutation

对于输入字符串“bba”,它不会生成所有整数排列。 将存储在数组中的整数是:2,1,1

输出为2 1 1。

我希望输出为:

1 1 2

1 2 1

2 1 1

#include <bits/stdc++.h>

int main() {
    std::string s;
    std::cout << "Enter a string: ";
    std::cin >> s;
    int ss = s.size();
    int ar[ss];
    for(int i=0; i<ss; i++) {
        int tmp = int(s[i])-96;
        ar[i] = tmp;
    }  

    do {
        for(auto i: ar) std::cout << i;
        std::cout << '\n';
    } while(std::next_permutation(ar, ar+ss));

    return 0;
}

2 个答案:

答案 0 :(得分:4)

你只得到一个排列的原因是因为在字典上没有排列的排列大于当前状态的排列:[2, 2, 1]。请参阅std::permutation的文档:

  

将范围[first,last]转换为下一个排列   按字典顺序排列的所有排列的集合   尊重运营商&lt;或comp。如果存在这样的排列,则返回true,   否则将范围转换为第一个排列(如同   std :: sort(first,last))并返回false。

在计算所有排列之前,请考虑使用std::vector而不是C数组并对其进行排序:

#include <string>
#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::string s = "bba";
    const int ss = s.size();
    std::vector<int> ar;
    ar.reserve(ss);
    constexpr int offset = 'a' - 1;
    for(int i=0; i<ss; i++) {
        int tmp = int(s[i]) - offset;
        ar.push_back(tmp);
    }  
    std::sort(ar.begin(), ar.end());
    do {
        for(auto i: ar) std::cout << i;
        std::cout << '\n';
    } while(std::next_permutation(ar.begin(), ar.end()));

    return 0;
}

输出:

122
212
221

Live example

更新:正如@Someprogrammerdude所指出的那样,请参阅:Why should I not #include <bits/stdc++.h>

更新2 :正如@ Jarod42所指出的那样,考虑使用'a' - 1代替魔术常量96

答案 1 :(得分:2)

在生成排列之前创建一个整数数组似乎是不必要的。 您缺少对值进行排序的点。

请尝试使用此方法:

std::sort(s.begin(), s.end());
do {
    for(int i = 0; i < s.size(); i++){
        std::cout << int(s[i]) - 96 << " ";
    }
    std::cout << '\n';
} while(std::next_permutation(s.begin(), s.end()));

输出

1 2 2                                                                                                                                                                                       
2 1 2                                                                                                                                                                                       
2 2 1