c++ - 创建集合成员的每个排列和符号变化的集合 (C++)

标签 c++ recursion vector set

假设我得到一个未知大小的 vector 。例如,它可以是

std::vector<int> myset1({1, 2, 3});

或者它可以是任何其他东西。那只是一个例子。现在,假设我想编写一个返回 vector vector 的函数。但是,此 vector 中的每个 vector 必须是原始 vector 的不同排列。所以在这种情况下,我希望该函数返回一个包含集合 {1, 2, 3}, {1, 3, 2}, {2, 1, 3}, {2, 3, 1}, { 3, 1, 2} 和​​ {3, 2, 1}(不注意顺序)。

通过某种递归,这可能很简单。但是,如果我还想考虑每个元素的符号怎么办?例如:

std::vector<int> myset2({1, 2});

我希望函数返回 {1, 2}, {1, -2}, {-1, 2}, {-1, -2}, {2, 1}, {2, -1} , {-2, 1}, {-2, -1}(我不关心顺序)。

我正在努力想出一种优雅地设计它的方法。正如您可以想象的那样,对于更大的集合,使用这样的函数而不是手动列出每个集合变得很有必要,但目前我没有想到任何想法。你将如何实现这一目标?

最佳答案

第一次尝试:

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

std::vector<std::vector<int>> all_permutations(std::vector<int> input)
{
    std::vector<std::vector<int>> result;

    std::sort(begin(input), end(input));
    input.erase(std::unique(begin(input), end(input)), end(input));
    do {
        result.push_back(input);
    } while(std::next_permutation(begin(input), end(input)));

    return result;
}

template<class T>
void emit(std::ostream& os, std::vector<T> const& v)
{
    os << "  [";
    const char* sep = " ";
    for (auto&& x : v) {
        os << sep << x;
        sep = ", ";
    }
    os << "]\n";
}

template<class T>
void emit(std::ostream& os, std::vector<std::vector<T>> const& v)
{
    os << "[\n";
    for (auto&& x : v) {
        emit(os, x);
    }
    os << "]\n";
}

int main()
{
    emit(std::cout, all_permutations({ 1, 2, 3 }));
}

预期输出;

[
  [ 1, 2, 3]
  [ 1, 3, 2]
  [ 2, 1, 3]
  [ 2, 3, 1]
  [ 3, 1, 2]
  [ 3, 2, 1]
]

现在添加加号和减号的代码:

#include <vector>
#include <algorithm>
#include <iostream>
#include <iterator>

std::vector<std::vector<int>> all_permutations(std::vector<int> input)
{
    std::vector<std::vector<int>> result;

    std::sort(begin(input), end(input));
    input.erase(std::unique(begin(input), end(input)), end(input));
    do {
        result.push_back(input);
    } while(std::next_permutation(begin(input), end(input)));

    return result;
}

template<class T>
void emit(std::ostream& os, std::vector<T> const& v)
{
    os << "  [";
    const char* sep = " ";
    for (auto&& x : v) {
        os << sep << x;
        sep = ", ";
    }
    os << "]\n";
}

template<class T>
void emit(std::ostream& os, std::vector<std::vector<T>> const& v)
{
    os << "[\n";
    for (auto&& x : v) {
        emit(os, x);
    }
    os << "]\n";
}

std::vector<int> plus_and_minus(std::vector<int> v)
{
    std::vector<int> inverse;
    inverse.reserve(v.size());
    std::transform(begin(v), end(v), back_inserter(inverse), [](auto&& x) { return -x; });
    v.insert(end(v), begin(inverse), end(inverse));
    sort(begin(v), end(v));
    inverse.erase(unique(begin(v), end(v)), end(v));
    return v;
}

int main()
{
    emit(std::cout, all_permutations(plus_and_minus({ 1, 2, 3 })));
}

预期:

[
  [ -3, -2, -1, 1, 2, 3]
  [ -3, -2, -1, 1, 3, 2]
  [ -3, -2, -1, 2, 1, 3]
  [ -3, -2, -1, 2, 3, 1]
  [ -3, -2, -1, 3, 1, 2]
  [ -3, -2, -1, 3, 2, 1]
  [ -3, -2, 1, -1, 2, 3]
  [ -3, -2, 1, -1, 3, 2]
  [ -3, -2, 1, 2, -1, 3]
  [ -3, -2, 1, 2, 3, -1]
  [ -3, -2, 1, 3, -1, 2]
  [ -3, -2, 1, 3, 2, -1]
  [ -3, -2, 2, -1, 1, 3]
  [ -3, -2, 2, -1, 3, 1]
  [ -3, -2, 2, 1, -1, 3]
  [ -3, -2, 2, 1, 3, -1]
  [ -3, -2, 2, 3, -1, 1]
  [ -3, -2, 2, 3, 1, -1]
  [ -3, -2, 3, -1, 1, 2]
  [ -3, -2, 3, -1, 2, 1]
  [ -3, -2, 3, 1, -1, 2]
  [ -3, -2, 3, 1, 2, -1]
  [ -3, -2, 3, 2, -1, 1]
  [ -3, -2, 3, 2, 1, -1]
  [ -3, -1, -2, 1, 2, 3]
  [ -3, -1, -2, 1, 3, 2]
  [ -3, -1, -2, 2, 1, 3]
  [ -3, -1, -2, 2, 3, 1]
  [ -3, -1, -2, 3, 1, 2]
  [ -3, -1, -2, 3, 2, 1]
  [ -3, -1, 1, -2, 2, 3]
  [ -3, -1, 1, -2, 3, 2]
  [ -3, -1, 1, 2, -2, 3]
  [ -3, -1, 1, 2, 3, -2]
  [ -3, -1, 1, 3, -2, 2]
  [ -3, -1, 1, 3, 2, -2]
  [ -3, -1, 2, -2, 1, 3]
  [ -3, -1, 2, -2, 3, 1]
  [ -3, -1, 2, 1, -2, 3]
  [ -3, -1, 2, 1, 3, -2]
  [ -3, -1, 2, 3, -2, 1]
  [ -3, -1, 2, 3, 1, -2]
  [ -3, -1, 3, -2, 1, 2]
  [ -3, -1, 3, -2, 2, 1]
  [ -3, -1, 3, 1, -2, 2]
  [ -3, -1, 3, 1, 2, -2]
  [ -3, -1, 3, 2, -2, 1]
  [ -3, -1, 3, 2, 1, -2]
  [ -3, 1, -2, -1, 2, 3]
  [ -3, 1, -2, -1, 3, 2]
  [ -3, 1, -2, 2, -1, 3]
  [ -3, 1, -2, 2, 3, -1]
  [ -3, 1, -2, 3, -1, 2]
  [ -3, 1, -2, 3, 2, -1]
  [ -3, 1, -1, -2, 2, 3]
  [ -3, 1, -1, -2, 3, 2]
  [ -3, 1, -1, 2, -2, 3]
  [ -3, 1, -1, 2, 3, -2]
  [ -3, 1, -1, 3, -2, 2]
  [ -3, 1, -1, 3, 2, -2]
  [ -3, 1, 2, -2, -1, 3]
  [ -3, 1, 2, -2, 3, -1]
  [ -3, 1, 2, -1, -2, 3]
  [ -3, 1, 2, -1, 3, -2]
  [ -3, 1, 2, 3, -2, -1]
  [ -3, 1, 2, 3, -1, -2]
  [ -3, 1, 3, -2, -1, 2]
  [ -3, 1, 3, -2, 2, -1]
  [ -3, 1, 3, -1, -2, 2]
  [ -3, 1, 3, -1, 2, -2]
  [ -3, 1, 3, 2, -2, -1]
  [ -3, 1, 3, 2, -1, -2]
  [ -3, 2, -2, -1, 1, 3]
  [ -3, 2, -2, -1, 3, 1]
  [ -3, 2, -2, 1, -1, 3]
  [ -3, 2, -2, 1, 3, -1]
  [ -3, 2, -2, 3, -1, 1]
  [ -3, 2, -2, 3, 1, -1]
  [ -3, 2, -1, -2, 1, 3]
  [ -3, 2, -1, -2, 3, 1]
  [ -3, 2, -1, 1, -2, 3]
  ...etc

http://coliru.stacked-crooked.com/a/82a4c5784dc0070d

关于c++ - 创建集合成员的每个排列和符号变化的集合 (C++),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46128661/

相关文章:

c++ - 二叉树的递归搜索同时返回 true 和 false

c++ - 迭代 vector 时跳过行

c++ - push_back() 是否总是增加 vector 的大小?

c++ - vector 迭代器不是增量 .erase()

c++ - `ios::hex` 是什么类型?

c++ - 用颜色代替颜色?

c++ - cmake,使用/MD 和 find_package(Boost) 构建

c++ - std::set 使用 char * 类型查找行为

c - gcd()函数中递归调用的次数

php - 用于匹配 CSS 媒体查询的递归/子例程正则表达式