【问题标题】:All permutations of size N and N is not necessarily equal to size of array大小 N 和 N 的所有排列不一定等于数组的大小
【发布时间】:2017-05-19 10:23:18
【问题描述】:

我有一个字符串向量,其值为{"Soa", "8", "m", "4", "8"}

我想从大小为k 的数组中打印指定大小n 的所有排列而不重复(但允许重复,如上面向量中的“8”)。我已经搜索了这个问题的解决方案,但找不到任何适合这种情况的解决方案。

目前的代码是:

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

int main()
{
    std::vector<std::string> arr = { "Soa", "4", "m", "8", "8" };
    std::sort(arr.begin(), arr.end());


        do {
            for(auto& i: arr)
                std::cout << i;

            std::cout << '\n';
        } while(std::next_permutation(arr.begin(), arr.end()));
}

此代码仅打印向量大小的所有排列 (n=k),因此它打印除 n=5 之外的我需要的内容。我想要指定n,例如让n=2 生成这些排列(它们的打印顺序无关紧要):

48
4Soa
4m
84
88
8Soa
8m
Soa4
Soa8
Soam
m4
m8
mSoa

编辑:Nathan 链接的解决方案不起作用,它将 84 视为 48。仍在寻找解决方案。

【问题讨论】:

  • 相关/重复,我认为它不排除重复:stackoverflow.com/questions/5095407/…
  • 嗨,问题和解释与我不符
  • @Trailo 他们解决这个问题的方法是将结果存储在std::set 中。这将确保您只获得唯一的排列。
  • @NathanOliver 问题是我需要生成大约 50 GB 的这些字符串,这比我在 std::set 中保留的内存要多得多。
  • 你打算用 50 GB 这样的字符串做什么?

标签: c++ algorithm


【解决方案1】:

这个简单的函数在执行时间上并不是最优的,但它相当快并且在程序员的时间里绝对是高效的。它通过循环遍历排列但跳过不改变 k 元素前缀的排列来构造部分排列。向量必须在开头排序;否则事情会严重破裂。

template<typename BidiIt>
bool next_partial_permutation(BidiIt first, BidiIt middle, BidiIt last) {
  std::reverse(middle, last);
  return std::next_permutation(first, last);
}

该功能取决于next_permutation 按字典顺序生成排列这一事实。因此,它可以直接从具有给定 k 前缀的第一个排列到具有该前缀的最后一个排列,只需反转从位置 k 开始的向量即可。

(具有给定 k 前缀的第一个排列对位置 k 开始的元素进行了排序;最后一个排列使这些元素以相反的顺序排序;因此反转这些元素意味着对 next_permutation 的下一次调用将产生下一个前缀。)

该函数是从this answer 复制粘贴的,但我认为这些问题不够相似,不足以认定为重复。

这是一个如何使用它的示例。程序的第一个命令行参数应该是k,然后是向量的n 元素。 (它在开始之前对向量进行排序,因此您无需确保对命令行参数进行排序。)

int main(int argc, char** argv) {
    size_t k = std::atoi(argv[1]);
    std::vector<std::string> words(argv + 2, argv + argc);
    std::sort(words.begin(), words.end());
    do {
        for (size_t i = 0; i < k; ++i) std::cout << words[i];
        std::cout << '\n';
    } while (next_partial_permutation(words.begin(), words.begin() + k, words.end()));
    return 0;
}

示例输出 (live on coliru)

$ ./a.out 2 "Soa" "8" "m" "4" "8"
48
4Soa
4m
84
88
8Soa
8m
Soa4
Soa8
Soam
m4
m8
mSoa

【讨论】:

    猜你喜欢
    • 2021-04-14
    • 2020-07-11
    • 2013-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多