【问题标题】:Check if sum possible in array检查数组中的总和是否可能
【发布时间】:2021-08-28 02:33:56
【问题描述】:

给定一个由N 非负整数组成的数组和一个target 和,检查是否可以通过选择数组中的一些元素并将它们相加来获得target。 (一个元素可以多次选择)。

我试图想出一个强力递归解决方案。我的想法是,对于每个元素,我们有 3 个选择

  1. 包含元素并保持在同一个索引中
  2. 包含元素并移动到下一个索引
  3. 排除元素并移动到下一个索引

这是我的 C++ 代码

bool checkSum(vector<int> &arr,int i, int n, int target)
{
    if(target==0)
        return true;
    if(i>=n or target<0)
        return false;

    return (checkSum(arr, i+1, n, target) or // don't include current value and move to next
            checkSum(arr, i, n, target-arr[i]) or // include current value 
            checkSum(arr, i+1, n, target-arr[i])); // include current value and move to next
}

对于某些测试用例,此代码似乎失败

arr = [10,7,0,6,2,6] target = 11   

我无法找出问题所在。

驱动程序代码

int main()
{
    int n, target;
    cin >> n >> target;
    vector<int> arr(n);
    for (int i = 0; i < n; i++)
        cin >> arr[i];

    if (checkSum(arr, 0, n, target))
        cout << "YES\n";
    else
        cout << "NO\n";

    return 0;
}

PS:我不是在寻找动态编程解决方案,因为我只想先把我的基础打好。如果我能知道我在这段代码中遗漏了什么,那就太好了。

【问题讨论】:

  • 您是否尝试过使用调试器?请出示minimal reproducible example
  • 如何检查 (target % current sum == 0)
  • 定义“失败”。它提出了正确的答案吗?会挂吗?您是否尝试过在每次调用 checkSum() 时打印一些内容,以便查看您所走的阵列路径?

标签: c++ arrays algorithm recursion


【解决方案1】:

感谢@BillLynch,当任何值为 0 时,代码似乎都会失败。所以我只是添加了一个额外的条件,它现在似乎可以工作了。

bool checkSum(vector<int> &arr,int i, int n, int target)
{
    if(target==0)
        return true;
    if(i>=n or target<0)
        return false;
    
    return (checkSum(arr, i+1, n, target) or // don't include current value and move to next
            arr[i]!=0 and   // include only if non-zero value
            (checkSum(arr, i, n, target-arr[i]) or // include current value 
            checkSum(arr, i+1, n, target-arr[i]))); // include current value and move to next
}

【讨论】:

  • 接受他的回答,这样这个问题就可以结束了
【解决方案2】:

第二次递归导致函数无限递归,就像arr[i] = 0、checkSum(arr, i, n, target) 将调用将无限运行的checkSum(arr, i, n, target-0)。

多次添加0是没有意义的,所以唯一需要改变的是避免arr[i] == 0时的第二次递归

bool checkSum(vector<int> &arr,int i, int n, int target)
{
    if(target==0)
        return true;
    if(i>=n or target<0)
        return false;

    return (checkSum(arr, i+1, n, target) or // don't include current value and move to next
            (arr[i] ? checkSum(arr, i, n, target-arr[i]) : false) or // include current value 
            checkSum(arr, i+1, n, target-arr[i])); // include current value and move to next
}

【讨论】:

    【解决方案3】:

    如果数组中有一个非正数(例如零),您的解决方案将永远不会停止迭代。

    【讨论】:

    • 问题是非负数。您一定是想说如果数组元素为 0,它将无限循环,对吧?
    • @BeshambherChaukhwan:零是会触发此问题的非正数。
    • 那么这里有什么我可以添加/修改以便处理零大小写的吗?
    • @Dev5:如果元素为零,则永远不要包含该元素。
    • @BillLynch 好的,谢谢.. 我想我可以在进行最后 2 次递归调用之前检查该条件
    猜你喜欢
    • 2022-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-07
    • 1970-01-01
    • 2023-04-03
    • 2014-06-27
    • 2015-02-19
    相关资源
    最近更新 更多