使用递归搜索整数数组中元素的所有组合

Posted

技术标签:

【中文标题】使用递归搜索整数数组中元素的所有组合【英文标题】:Using recursion to search all combinations of elements in an array of integers 【发布时间】:2015-06-21 10:47:41 【问题描述】:

我正在使用 JS 从 Coderbyte 解决这个问题:

让函数 ArrayAdditionI(arr) 获取存储在 arr 中的数字数组,如果数组中的任何数字组合可以相加等于数组中的最大数字,则返回字符串 true,否则返回字符串假。例如:如果 arr 包含 [4, 6, 23, 10, 1, 3],则输出应返回 true,因为 4 + 6 + 10 + 3 = 23。数组不会为空,不会包含所有相同的元素,并且可能包含负数。

鉴于需要探索数组元素的各种组合的分支性质,递归解决方案似乎已经成熟。我还想使用递归来获得一些额外的练习。我对编码还是很陌生。

这是我想出的解决方案,我对此非常满意,直到我开始测试并发现它根本不是解决方案:

function ArrayAdditionI(arr)  
  // sorting the array to easily remove the biggest value
  var sArr = arr.sort(function (a, b) 
    return a-b;);
  // removing the biggest value
  var biggest = sArr.pop();
  // count will be iterated to stop the recursion after the final element of the array has been processed
  var count = 0;
  function recursion (start, i) 
    if (sArr[i] + start === biggest) 
      return true;
    
    else if (start + sArr[i] < biggest) 
      return recursion(start + sArr[i], i+1);
    
    else if (start + sArr[i] > biggest && count < sArr.length) 
      count++;
      return recursion(0, count);
    
    else 
      return false;
    
  
  return recursion(0,0);

只有当可以求和以满足基本情况的数组元素彼此相邻时,此代码才有效;例如,调用 ArrayAdditionI([1,2,3,4]) 将不起作用,因为必须将两个元素相加才能达到目标值(位置 0 中的“1”和位置 2 中的“3”)是不相邻。

我的流程将返回 1,然后是 1+2,然后是 1+2+3,然后是 2,然后是 2+3,然后是 3,最后返回 false,因为目标 (4) 是还没到。

我可以想象一个适当的解决方案需要如何流过给定的数组,但我不知道如何通过递归来实现这一点。对于给定的数组 [1,2,3,4],流程应该以这种模式检查结果:(position0, pos0+pos1, pos0+pos2, pos0+pos1+pos2, pos2, pos2+pos3, pos3)。谁能给我一个轻推?我会在一个小时后睡觉之前再考虑一下,然后在早上重新开始。也许我的大脑需要充电。

再一次,我对此很陌生,如果我犯了一些非常愚蠢的错误,请告诉我,我会从中吸取教训。谢谢!

【问题讨论】:

为什么你会以字符串形式返回真/假? 你的模式缺少一些东西,比如 pos1, pos2, pos0+pos3, pos1+pos3, pos1+pos2, pos0+pos1+pos2+pos3... 你能设计一个更简单的方案吗? 【参考方案1】:

你的算法有缺陷。您的功能看起来只有一步。 你需要在里面添加循环来查看所有的剩余值。

function ArrayAdditionI(arr) 
    // sorting the array to easily remove the biggest value
    // slice added to prevent original array modification
    var sArr = arr.slice().sort(function (a, b)  
        return a - b;
    );
    // removing the biggest value
    var biggest = sArr.pop();
    function recursion(start, i) 
        var result = false;
        // looking over all rest values of array
        for (var j = i; j < sArr.length && !result; j++) 
            if (sArr[j] + start === biggest) 
                result = true;
            
            else if (start + sArr[j] < biggest) 
                result = recursion(start + sArr[j], j + 1);
            
        
        return result;
    
    return recursion(0, 0);

【讨论】:

不错的解决方案!我最终坚持使用递归 througout.. 我会发布我的想法【参考方案2】:
function ArrayAdditionI (arr) 
    var sArr = arr.sort(function (a,b) 
        return a-b;
    );
    var biggest = sArr.pop();
    function recursion (start, indx) 
        if (start + sArr[indx] === biggest) 
            return true;
        
        else if (sArr.length < indx) 
            return false;
        
        else if (start + sArr[indx] < biggest) 
            return recursion(start + sArr[indx], indx + 1) || recursion(start, indx+1)
        
        else 
            return false;
        
    
    return recursion(0,0);

【讨论】:

我认为你的数组长度基本情况倒退了。您将使用此代码访问超出范围的索引。

以上是关于使用递归搜索整数数组中元素的所有组合的主要内容,如果未能解决你的问题,请参考以下文章

PostgreSQL 在递归查询中找到所有可能的组合(排列)

递归与回溯:python列表组合问题

使用java,列举所有给定数组中和为定值的组合

40. 组合总和 II-递归dfs+剪枝-中等难度

递归 - 与数组结合,Java 中不重复

递归与回溯9:子集问题-求子集