【问题标题】:Print all permutation of a fixed number of integers that adds up to k打印加起来为 k 的固定数量整数的所有排列
【发布时间】:2018-12-03 22:54:50
【问题描述】:

假设我有一个数组初始化为 0,大小为 n

我想打印所有n 正整数的排列,加起来是一个正整数k

我的代码目前只打印一些排列(正确的排列,但仍然缺少一些)。

例如,对于n = 4k = 3,我的代码正在打印:

1 1 1 0
1 1 0 1
1 0 2 0
1 0 1 1
1 0 1 1
1 0 0 2
0 2 1 0
0 2 0 1
0 1 2 0
0 1 1 1
0 1 1 1
0 1 0 2
0 1 2 0
0 1 1 1
0 0 3 0
0 0 2 1
0 0 2 1
0 0 1 2
0 1 1 1
0 1 0 2
0 0 2 1
0 0 1 2
0 0 1 2
0 0 0 3

您可以看到它缺少一些排列。例如:3 0 0 00 3 0 0 等。

代码:

#include <iostream>

void printArray(int* a, int arraySize){
    for(int i = 0; i < arraySize; i++)
        std::cout << a[i] << " ";
    std::cout << std::endl;
}

int currentSum(int* a, int arraySize){
    int sum = 0;
    for(int i = 0; i < arraySize; i++)
        sum += a[i];
    return sum;
}

void printAll(int* a, int arraySize, int k, int beg){
    for(int i = beg; i < arraySize; i++){
        if(currentSum(a, arraySize) == k)
            printArray(a, arraySize);
        else{
            a[i]++;
            printAll(a, arraySize, k, beg+1);
            a[i]--;

        }
    }
}

int main(){
    int k = 3; //array must add up to k, exactly
    int arraySize = 4;
    int* a = new int[arraySize];
    for(int i = 0; i < arraySize; i++)
        a[i] = 0;
    printAll(a, arraySize, k, 0);
}

【问题讨论】:

  • 我建议使用调试器逐语句逐句执行代码,观察变量中的值。
  • 注释掉你所有的代码,直到你有一个打印所有排列的程序。让这个工作。然后您可以将数字与int numerical_value = text_number[i] - '0'; 相加。
  • 这些东西不叫排列。 0 不是正整数。

标签: c++ recursion sum permutation


【解决方案1】:

您只增加a[0] 一次,因为只有第一次调用printAllbeg 值为0。a[1] 可以增加两次,a[2] 三次等。

您需要更改printAll 中的循环,以便能够多次增加a[i]

【讨论】:

  • 我如何知道我应该在i-th 迭代中迭代多少次?
【解决方案2】:

如果将来有人需要这个...

我遵循Thomas Matthews 的建议,开始寻找显示所有排列(有重复)的解决方案。

我发现this answer 正是这样做的。我只需要稍微调整一下我的代码,它现在就可以正常工作了。

#include <iostream>
#include <vector>

template <class Iter>
bool next_variation(Iter first, Iter last, const typename std::iterator_traits<Iter>::value_type max){
    if(first == last) return false;
    Iter i(last); --i;
    if(*i < max) { ++(*i); return true; }
    while( i != first ){
        *i = 0;
        --i;
        if(*i < max) { ++(*i); return true; }
       }
    return false;
}

void printVector(std::vector<int> a){
    for(std::vector<int>::const_iterator it = a.begin(); it!= a.end(); ++it)
        std::cout << *it << " ";
    std::cout << std::endl;
}

int currentSum(std::vector<int> a){
    int sum = 0;
    for(std::vector<int>::const_iterator it = a.begin(); it!= a.end(); ++it)
        sum += *it;
    return sum;
}

void printAll(std::vector<int> a, int k){
    do{
        if(currentSum(a) == k)
            printVector(a);
      }
    while( next_variation(a.begin(), a.end(), a.size()) );
}

int main(){
    int k = 3; //array must add up to k, exactly
    int arraySize = 4;

    std::vector<int> a(arraySize,0); // Initialized with 0
    printAll(a, k);

}

输出是:

0 0 0 3
0 0 1 2
0 0 2 1
0 0 3 0
0 1 0 2
0 1 1 1
0 1 2 0
0 2 0 1
0 2 1 0
0 3 0 0
1 0 0 2
1 0 1 1
1 0 2 0
1 1 0 1
1 1 1 0
1 2 0 0
2 0 0 1
2 0 1 0
2 1 0 0
3 0 0 0

正如预期的那样。

【讨论】:

  • 由于这个问题被标记为 C++,我建议改用 std::next_permutation
  • 我想到了@user2176127。我可能是错的,但至少从那里给出的例子来看,它似乎没有提供重复排列。不过我可能错了。
  • 它确实返回排列,又名 n!安排您提供的元组的可能性:ideone.com/3m1LvR 我不确定排列是否是您在这里所做的正确术语。
  • @user2176127 也许我的问题中的措辞不好(非常欢迎任何编辑)。但是,我需要“排列”,例如1111
  • 这假设数组中的所有数字都不大于数组大小,这是你想要的吗? IOW k=5 和 n=2 的答案是什么?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-19
  • 2015-08-03
  • 2013-07-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多