【问题标题】:Return Path at the root node when using recursion使用递归时返回根节点的路径
【发布时间】:2016-08-26 05:54:57
【问题描述】:

我正在尝试为subset-sum problem 创建一个递归函数。我创建了一个受this answer 启发的函数。

问题:我正在尝试从某个数组(例如 [50,40,30,20])中选择一些元素,其总和被赋予我定义为 sum 的某个值(例如 100)。

我已经按照该答案的建议创建了稍微修改的函数。

从前面捡起,选择或不选择。

如果我选择一个元素,缩减列表中的总和将小于选择的元素,否则如果我不选择该元素,缩减列表中的总和将是原始的。

但是,我发现最困难的是返回跟踪到递归调用根节点的路径。当我到达 sum 匹配的节点时,我能够打印路径。

这是我的功能:

private static boolean findSumFromSubList(ArrayList<Integer> set, Integer sum, ArrayList<Integer> result) {

    if (sum < 0)
        return false;

    if (sum == 0) {
        // Got it! Awesome! Print it!
        System.out.println(result);
        return true;
    }

    if (set.size() == 0 && sum != 0)
        return false;

    ArrayList<Integer> newSet = new ArrayList<>(set);
    newSet.remove(0);

    System.out.println("Left: Picking up " + set.get(0));
    result.add(set.get(0));
    if (findSumFromSubList(newSet, sum - set.get(0), new ArrayList<>(result))) {
        return true;
    }

    System.out.println("Right: NOT Picking up " + set.get(0));
    result.remove(result.size()-1);
    if (findSumFromSubList(newSet, sum, new ArrayList<>(result))) {
        return true;
    }

    return false;
}

我这样称呼它:

    ArrayList<Integer> pair = new ArrayList<>();
    pair.add(50);
    pair.add(40);
    pair.add(30);
    pair.add(20);
    ArrayList<Integer> result = new ArrayList<>();
    boolean resultBool = findSumFromSubList(pair, 100, result);

    System.out.println("bool: " + resultBool + ", result: " + result);

我得到的输出是:

Left: Picking up 50
Left: Picking up 40
Left: Picking up 30
Right: NOT Picking up 30
Left: Picking up 20
Right: NOT Picking up 20
Right: NOT Picking up 40
Left: Picking up 30
Left: Picking up 20
[50, 30, 20]
bool: true, result: [50]

所以我能够在递归中获得输出,但是我怎样才能将该值返回给根调用函数。因为result 只返回 50。

【问题讨论】:

  • 提示:错误的命名 - “getSum()” 听起来像:它得到一个总和。最好称它为 hasSublistThatHasGivenSum" 或类似的总和。
  • @GhostCat 是的,我只是在玩它以使其正常工作。已编辑

标签: java recursion tail-recursion


【解决方案1】:

不要复制result,而是尝试传递它,以便在递归时对其进行修改。

private static boolean getSum(ArrayList<Integer> set, Integer sum, LinkedList<Integer> result) {
    // ...

    System.out.println("Left: Picking up " + set.get(0));
    result.add(set.get(0));
    if (getSum(newSet, sum - set.get(0), result)) {
        return true;
    }
    result.removeLast();

    System.out.println("Right: NOT Picking up " + set.get(0));
    if (getSum(newSet, sum, result)) {
        return true;
    }
}

您可以将类似的逻辑应用于set,但我将把它作为练习留给读者。

【讨论】:

  • 嘿!有效!优秀的。在哪里更改结果数组令人困惑。你能解释一下你使用result.addresult.remove的那两条线吗?
  • 它就像一个堆栈。我们将当前的尝试推到顶部,并在失败时将其弹出。
  • 我不是在数组列表中用result.add(set.get(0))result.remove(result.size()-1) 做同样的事情吗?
  • 如果你这样做了,它不在你的帖子中。
  • 但是,最后我得到了 50。其他所有内容都弹出,直到结束
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-12-17
  • 2012-03-14
  • 1970-01-01
  • 2019-05-27
  • 2018-12-31
  • 2010-08-12
  • 2021-06-30
相关资源
最近更新 更多