递归确定一组数字是否包含两个总和相等的子集

时间:2018-10-31 17:56:47

标签: java arrays recursion sum set

我需要弄清楚如何递归确定是否存在元素选择,以使选定元素的总和与给定整数列表的未选定元素的总和相同。

例如,集合 nums = [1,3,5,3]返回 true ,因为子集可以是[3,3]和[1,5],这两个列表的总和为6,因此该方法应返回 true 。如果该子集不存在,则应返回 false

我有代码:

private static boolean canFind(int[] nums, int index, int sumOne, int sumTwo) {
    if (index == nums.length) {
        return false;
    }

    if (oneSum == twoSum) {
        return true;
    }

    if (oneSum < twoSum) {
        return canFind(nums, index + 1, sumOne + nums[index], sumTwo);
    }

    return canFind(nums, index + 1, sumOne, sumTwo + nums[index]);
}

但是我不知道为什么这不起作用,甚至为什么不起作用。

1 个答案:

答案 0 :(得分:1)

递归canFind()方法的思想是:

  • 如果我已经处理了数字,直到位置index,并且 到目前为止,已经收集了两个总和sumOnesumTwo,是否有可能 找到剩余数字的解决方案?

在详细查看代码之前,让我们进一步澄清一下任务(如果我理解正确的话):为了找到有效的解决方案,必须对每个数字进行计数,无论是sumOne还是{{1 }}。不允许跳过数字或同时计算两个数字。

因此,在解决方案过程中的任何时候,您都可以选择是在sumTwo还是sumOne中添加当前数字,这就是您在两个递归调用中正确执行的操作< / p>

sumTwo

    canFind(nums, index + 1, sumOne + nums[index], sumTwo)

但是通话周围有问题。您不知道将当前数字添加到 canFind(nums, index + 1, sumOne, sumTwo + nums[index]) sumOne对于解决方案是否正确,因此您应该尝试两种方式,如果其中一种成功,则返回true。如果较小,您的代码将添加到sumTwo,否则添加到sumOne。尽管这似乎是合理的,但这并不一定导致解决方案。因此,您应该将该部分更改为

sumTwo

我们必须继续尝试多长时间?直到我们到达数组末尾为止,因为我们不允许遗漏任何数字。

当我们到达数组末尾时,是否有解决方案?如果两个和相等,这是一个解决方案。

因此,在尝试递归调用之前,我们应该检查数组的结尾:

    if (canFind(nums, index + 1, sumOne + nums[index], sumTwo)) {
        // if there's some solution by adding to sumOne, we're finished.
        return true;
    } else if (canFind(nums, index + 1, sumOne, sumTwo + nums[index])) {
        // if there's some solution by adding to sumTwo, we're finished.
        return true;
    } else {
        // if both tries didn't succeed, thre's no solution 
        // starting from the given situation
        return false;
    }

将它们放在一起:

    if (index == nums.length) {
        if (sumOne == sumTwo) {
            return true;
        } else {
            return false;
        }
    }

这基本上应该可以完成工作。