简体   繁体   English

递归地确定数组中的元素是否可以求和 - C ++

[英]Recursively determine whether elements in array can sum to target - C++

I am doing practice with recursion and trying small problems. 我正在练习递归和尝试小问题。 One of the functions I am trying to design comboSum takes in an array of integers, its size, and a target value. 我试图设计comboSum的一个函数是一个整数数组,它的大小和一个目标值。 It returns true if a combination of any of the elements (can only use each element once) adds to the target value. 如果任何元素的组合(只能使用每个元素一次)添加到目标值,则返回true。 This is my implementation so far. 到目前为止,这是我的实现。

// Expected Behaviors
// comboSum([1, 2, 3], 3, 0) => false
// comboSum([2, 4, 8], 3, 12) => true
// comboSum([2, 4, 8], 3, 11) => false
// comboSum([], 0, 0) => true

bool comboSum(const int a[], int size, int target)
{
    if (target == 0)
        return true; // if we have decremented target to zero
    if (target != 0 && size == 0)
        return false; // if we havent hit target to zero and we have no more elements

    size--;

    return (comboSum(a, size, target) || comboSum(a, size, target - a[size]));

    // OR logic ensures that even if just one sum exists, this returns true
}

My algorithm works except for the case of an array with all non-zero values and the target being zero. 我的算法工作,除了具有所有非零值且目标为零的数组的情况。 The function immediately returns true without checking for a valid summation. 该函数立即返回true而不检查有效求和。

// comboSum({1, 2, 3}, 3, 0) returns true when this should be false

What are some possible ways to correct this issue? 有哪些方法可以解决这个问题?

Edit: I cannot change the parameters or call any additional helper functions. 编辑:我无法更改参数或调用任何其他辅助函数。 The function header must remain as is and I must solve the problem recursively (no use of for or while loops or STL algorithms) 函数头必须保持原样,我必须递归地解决问题(不使用for或while循环或STL算法)

A simple solution is to keep the size parameter fixed and have another parameter that indicates the current position of the recursion. 一个简单的解决方案是保持size参数固定,并有另一个参数指示递归的当前位置。

bool comboSum(const int *a, int size, int pos, int target) {
    if (target == 0)
        return pos < size || size == 0; // true if pos has moved or if the array is empty
    else if (pos == 0)
        return false;

    pos--;
    return comboSum(a, size, pos, target) || comboSum(a, size, pos, target - a[pos]);
}

This solution handles your test cases correctly, but we have to pass the pos argument after the size argument. 此解决方案正确处理您的测试用例,但我们必须在size参数后传递pos参数。 Both arguments should start with the same value: 两个参数都应以相同的值开头:

// comboSum([1, 2, 3], 3, 3, 0) => false
// comboSum([2, 4, 8], 3, 3, 12) => true
// comboSum([2, 4, 8], 3, 3, 11) => false
// comboSum([], 0, 0, 0) => true

C++ in Practice C ++实践

Since this question is tagged as C++, it would be a good idea to use a class that gives us more flexibility than C arrays. 由于这个问题被标记为C ++,因此使用一个比C数组更灵活的类是个好主意。 For example, we could use a std::vector . 例如,我们可以使用std::vector If that's the case, then we don't need an extra parameter for the size of the list: 如果是这种情况,那么我们不需要额外的参数来表示列表的大小:

#include <vector>

bool comboSum(std::vector<int>& v, size_t pos, int target)
{
    if (target == 0) {
        return pos < v.size() || v.size() == 0;
    } else if (pos == 0) {
        return false;
    }
    pos--;
    return comboSum(v, pos, target) || comboSum(v, size, target - v[pos]);
}

If you want to keep everything you have as-is, try adding a variable to count the number of recursions. 如果要保留原样,请尝试添加变量来计算递归次数。

bool comboSum(const int a[], int size, int target, int count = 0)
{
    if (target == 0 && size == 0 && count == 0)
        return false;
    else if (target == 0)
       return true;
    else if (target != 0 && size == 0)
       return false;

size--;

return (comboSum(a, size, target) || comboSum(a, size, target - a[size]));
};

Please note that there are definitely better ways to do this, but as a learning exercise it doesn't hurt to give this a go! 请注意,肯定有更好的方法可以做到这一点,但作为一个学习练习,这样做是不会有害的!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM