【问题标题】:Recursively determine if a set of numbers contains two subsets that equal in sum递归确定一组数字是否包含两个总和相等的子集
【发布时间】:2019-04-04 23:26:39
【问题描述】:

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

所以例如集合 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]);
}

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

【问题讨论】:

  • 能否请您显示可拆分方法,并且您也必须编辑您的代码,因为 oneSum 和 twoSum 没有声明,而且我没有看到此代码中有任何递归。
  • 你好。我认为如果您这样问,您的问题可能会更准确:“递归确定一组数字是否包含两个总和相等的子集”
  • 抱歉,可拆分方法已重命名为 canFind(这是一个递归函数,我只是忘记进行更改。将编辑问题。
  • 你能举例说明你是如何输入代码的吗?
  • 从同名的公共方法调用代码: public static boolean canFind(int[] nums) { return canFind(nums, 0, 0, 0);

标签: java arrays recursion sum set


【解决方案1】:

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

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

在详细查看您的代码之前,让我们再澄清一下任务(如果我理解正确的话):对于一个有效的解决方案,每个数字都必须计算在sumOnesumTwo 中。不允许跳过一个数字或同时计算一个数字。

因此,在求解过程中的任何时候,您都可以选择是将当前号码添加到 sumOne 还是 sumTwo,这就是您在两个递归调用中正确执行的操作

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

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

但是调用有问题。您不知道将当前数字添加到sumOnesumTwo 是否对解决方案是正确的,因此您应该尝试两种方法,如果其中一种方法成功,则返回true。如果代码更小,您的代码将添加到 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;
        }
    }

把它们放在一起:

private static boolean canFind(int[] nums, int index, int sumOne, int sumTwo) {
    if (index == nums.length) {
        // if we're at the end of the array, we can compare the sums
        // to decide whether this is a solution.
        if (sumOne == sumTwo) {
            return true;
        } else {
            return false;
        }
    }
    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;
    }
}

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

【讨论】:

  • 是的,这正是我想要的。非常感谢!
猜你喜欢
  • 2012-09-28
  • 2014-11-16
  • 1970-01-01
  • 1970-01-01
  • 2023-03-03
  • 1970-01-01
  • 1970-01-01
  • 2017-07-02
  • 2020-06-30
相关资源
最近更新 更多