如何使用递归从集合中选择所有可能的元素组合

时间:2017-03-16 15:29:38

标签: c++ recursion

这是来自hackerrank的问题;我试图理解递归是如何工作的。

手头的任务是:

  

找出可以表达给定整数 X 的方式的数量   作为独特自然数的 N 次幂的总和。

     

例如,如果 X = 100 N = 2

     

100 =10²=6²+8²=1²+3²+4²+5²+7²

     

所以100可以表示为3中唯一自然数的平方   不同的方式,所以我们的输出是3。

这是我的代码:

#include <cmath>
#include <iostream>

using namespace std;

int numOfSums(int x, int& n, const int k) {

    int count = 0, j;
    for (int i = (k + 1); (j = (int) pow(i, n)) <= x; i++) {
        j = x - j;

        if (j == 0)
            count++;
        else
            count += numOfSums(j, n, i);
    }

    return count;
}

int main() {
    int x, n;
    cin >> x >> n;
    cout << numOfSums(x, n, 0) << endl;
    return 0;
}

但是当我输入x = 100和n = 2时,它输出的是2,而不是3。代码有什么问题?

链接到问题: https://www.hackerrank.com/challenges/the-power-sum

1 个答案:

答案 0 :(得分:0)

当我使用此3运行它时,您的示例代码会返回main()

#include <iostream>
int main() {
    int x = 100, n = 2;
    cout << numOfSums(x, n, 0) << endl;
    return 0;
}

问题很可能是你正在使用double std::pow(double, int),但是你没有将结果四舍五入到最接近的整数((int)向下舍入)。你应该在截断之前添加½:

j = static_cast<int>(pow(i, n) + 0.5)

我使用了更多C ++风格的演员,我觉得更清楚。

实现对整数进行操作的等效std::pow()会更有效。如果你想要,那也可以是递归的:

unsigned long pow(unsigned long x, unsigned long n)
{
    return n ? x * pow(x, n-1) : 1;
}

迭代版本更有效(或尾递归版本和合适的优化编译器)。

缩减版本,我的更改:

template<typename T>
T powi(T x, T n)
{
    T r{1};
    for (;  n;  n /= 2) {
        r *= n%2 ? x : 1;
        x *= x;
    }
    return r;
}

template<typename T>
T numOfSums(T x, T n, T i = {})
{
    T count{}, j;
    for (++i;  (j = powi(i, n)) <= x;  ++i)
        count += j == x ? 1 : numOfSums(x-j, n, i);
    return count;
}

#include <iostream>
int main()
{
    unsigned long int x = 100, n = 2;
    std::cout << numOfSums(x, n) << std::endl;
    return 0;
}