【问题标题】:Saving Data in a recursive function to a list将递归函数中的数据保存到列表中
【发布时间】:2019-07-28 21:45:18
【问题描述】:

我正在开发一个函数,它使用递归调用将给定的输入分解为面额。

在每一步都递归成两个变体:

  1. 继续使用当前硬币:将其添加到列表中并递归。
  2. 切换到下一个硬币:增加硬币 pos 并递归。

除了在剩余 == 0 时打印出列表中捕获的面额组合之外,我还打算捕获该列表的值并从函数中返回它。

代码如下:

    static final int[] DENOMINATIONS = {9,5,3};

    private static void change(int remaining, List<Integer> coins, int pos)

        if (remaining == 0) {

       // This correctly prints the desired output. 
       // I want to return that exact value from the function.
            System.out.println(coins); 

        } else {
            if (remaining >= DENOMINATIONS[pos]) {
                coins.add(DENOMINATIONS[pos]);
                another.addAll(coins);
                change(remaining - DENOMINATIONS[pos], coins, pos);
                coins.remove(coins.size() - 1);
            }
            if (pos + 1 < DENOMINATIONS.length) {
                change(remaining, coins, pos + 1);
            }
        }
    }


    public static List<Integer> denominations(int amount) {
        List<Integer> result = new ArrayList<Integer>();
        List<Integer> another = new ArrayList<Integer>();
        change(amount, result, another ,0);
        System.out.println(another.size());
        return another;
    }

    public static void main(String[] args) {
        List<Integer> list = denominations(13);
        System.out.println(list);
    }

输出:[5,5,3]

【问题讨论】:

  • 这是基于 SICP 计数变化的例子吗?
  • 我想是的。

标签: java list algorithm recursion arraylist


【解决方案1】:

您必须在 change 方法的 and 中添加 return coins;,但您可以保持原样。返回和更改数组是一种代码味道,因为该方法既对对象进行操作(修改它)又返回结果。

为了让它工作,你可以定义你的denomination方法如下:

public static List<Integer> denominations(int amount) {
   List<Integer> result = new ArrayList<Integer>();
   change(amount, result, 0);
   return result;
}

编辑:

列表是空的,因为它唯一改变的地方是这里:

coins.add(DENOMINATIONS[pos]);
change(remaining - DENOMINATIONS[pos], coins, pos);
coins.remove(coins.size() - 1);

添加和删除元素的位置。是你写的让它空了:)

编辑2:

我建议传递第二个对象,这将是您要返回的列表的副本,并且不会被修改。

【讨论】:

  • 我已经尝试过了,但它仍然返回一个空列表。我根据你的建议修改了我的代码
  • 是的,你是对的。那是因为这些项目正在从列表中删除。这是我想在 if(remaining == 0) 时准确返回的列表的值。您建议在哪里修改?
  • 我已经添加了一个建议;)
【解决方案2】:

您似乎认为 java 是通过引用传递的,这是不正确的。 Java 方法是按值传递的。

我已经更新了你的代码:

改变方法:

private static List<Integer> change(int remaining, List<Integer> coins, int pos) { // Updated method return type;

    if (pos < 0 || pos >= DENOMINATIONS.length) { // check if position is invalid
        return new ArrayList<>(); // return an empty list
    }

    if (remaining == DENOMINATIONS[pos]) { // check if remaining is equal to denominations[pos]
        coins.add(DENOMINATIONS[pos]); // add the denominations to the coins result
        return coins; // return the result
    } else if (remaining > DENOMINATIONS[pos]) { // check if remaining is greater than denominations[pos]
        coins.add(DENOMINATIONS[pos]);// add the possible denominations to the coins result
        remaining = remaining - DENOMINATIONS[pos]; // calculate the new remaining
        if (remaining >= DENOMINATIONS[pos]) { // check if remaining is greater than or equal to denominations[pos]
            return change(remaining, coins, pos); // stick to this position
        } else {
            return change(remaining, coins, pos + 1); // increment pos to go to the lower denominations
        }
    } else if (remaining < DENOMINATIONS[pos]) { // check if remaining is lesser than denominations[pos]
        if (coins.isEmpty()) { // if coins is empty then go to the next denomination
            return change(remaining, coins, pos + 1);
        } else {
            coins.remove(coins.size() - 1); // remove the previous denomination
            return change(remaining + DENOMINATIONS[pos - 1], coins, pos); // go back to the previous remaining and // try this DENOMINATIONS[pos]
        }
    }
    return coins;
}

面额方法:

public static List<Integer> denominations(int amount) {
    return change(amount, new ArrayList<Integer>(), 0);
}

输入13
输出[5, 5, 3]

【讨论】:

  • 谢谢马克。它运作良好。如果您能在此处简要解释面额方法的必要性,我将不胜感激。我正在尝试理解基本概念。
  • 我只是试图让我的解决方案适合您的解决方案。不需要面额方法。您可以简单地将 change 方法调用到您的 main 方法中。
  • 这些函数为一些输入值(如 21 、 30 )返回一个空列表。知道为什么吗?
【解决方案3】:

change 应该返回布尔值,表示是否已找到答案。

所以change 的正文看起来像这样:

if (remaining == 0) {
  return true;
}
...
if (change(...)) return true;
...
return false;  // It's last line of body

【讨论】:

    猜你喜欢
    • 2020-04-26
    • 2014-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多