下面的解决方案背后的算法是什么

时间:2016-12-12 14:18:27

标签: java algorithm recursive-backtracking

我遇到了提高编码技能的递归练习,发现了以下问题。

给定一系列整数,是否可以选择一组整数,以便该组与给定目标相加?我们的约定不是查看整个数组,而是考虑从索引开始并继续到数组末尾的数组部分。调用者可以简单地通过将start作为0来指定整个数组。不需要循环 - 递归调用沿着数组向下进行。

groupSum(0, [2, 4, 8], 10) → true
groupSum(0, [2, 4, 8], 14) → true
groupSum(0, [2, 4, 8], 9) → false

经过2天的工作和学习,我什么都没有。我检查了给定的解决方案,我仍然无法理解解决方案后一步一步调试。

public boolean groupSum(int start, int[] nums, int target) {
  // Base case: if there are no numbers left, then there is a
  // solution only if target is 0.
  if (start >= nums.length) return (target == 0);

  // Key idea: nums[start] is chosen or it is not.
  // Deal with nums[start], letting recursion
  // deal with all the rest of the array.

  // Recursive call trying the case that nums[start] is chosen --
  // subtract it from target in the call.
  if (groupSum(start + 1, nums, target - nums[start])) return true;

  // Recursive call trying the case that nums[start] is not chosen.
  if (groupSum(start + 1, nums, target)) return true;

  // If neither of the above worked, it's not possible.
  return false;
} 

解决方案很短,其逻辑基于组合。你怎么看待这件事?它背后的算法有什么解释?

此致

3 个答案:

答案 0 :(得分:4)

这只是基本的回溯:

if (start >= nums.length) return (target == 0);

- 这里我们已经过了所有输入,并且当剩余的目标填充为0时,我们成功了。

if (groupSum(start + 1, nums, target - nums[start])) return true;

- 在这里,我们尝试使用start位置的元素填充目标:

  • 转移到下一个位置
  • 从目标中减去当前元素(这等于包括所选集合中的当前元素)
if (groupSum(start + 1, nums, target)) return true;

- 在这里,我们尝试使用位于start

的元素的而不使用

从最后一个元素中读取:

  • 如果没有更多元素,如果target为0
  • ,我们就成功了
  • 否则,如果我们可以使用或不使用当前元素
  • 匹配目标的剩余元素,我们就会成功

答案 1 :(得分:3)

所以,让我们说你的问题是:

  • 你能用数字[2,3,5,8]创建一个9的总和吗?

如果至少满足以下一个问题,则该问题属实:

  • 你可以用数字[3,5,8]创建一个9的总和吗?
  • 你可以用数字[3,5,8]创建一个7的总和吗?

因此,您将有关4元素列表的初始问题替换为关于3元素列表的两个新问题。

当你再三次这样做时,最终会得到16个关于0元素列表的问题。如果至少其中一个目标是零,那么你最初的问题的答案是肯定的。

答案 2 :(得分:0)

它基于dynamic programming。基本上你将一个问题分解为许多更容易解决的子问题。

以下是对此特定问题的一些解释:click.

相关问题