【问题标题】:How can I keep track of changes that happen during recursion如何跟踪递归期间发生的更改
【发布时间】:2021-10-10 22:05:42
【问题描述】:

我有一个数字列表,我试图将其有效地分类到不同大小的组中。我的组大小是 1000、500、300。这是一个装箱问题。所以如果我有一个列表

250、100

我会使用一个 300 大小的组,因为列表总数和总垃圾箱容量之间的差异是“浪费”。

因此,对于总计 1600 个的列表,可以做到的最好的将是 1 1000、1 500 和 1 300。

在给定剩余总数的情况下,我有逻辑来确定使用什么大小的垃圾箱。

因为在我的情况下,列表的顺序很重要,我不能简单地按最大然后 bin 包排序。一个列表

85、100、240、...

需要保持这个顺序。因此,为了有效地打包,我首先从列表的开头获取适合给定组的尽可能多的数字,然后将它们从列表中删除,这样它们就不会被使用两次。

问题是当我去调用递归函数时,我想传递给它一个剩下的数字列表。

我遇到的问题是我传递给递归文件的列表是通过引用传递的,所以后面的递归中发生的任何变化仍然存在于前面的递归中。如何在 C# 中解决这个问题?

编辑:我正在添加更多示例,希望能更完整地解释我的问题

这会很长,所以我很抱歉。我将举一个冗长的例子来说明我的困境。

假设我有一个清单

100、115、105、205、195、240、240、130、180、140、225、85

总共是 1960。所以我想创建 2 1000 个组。安全系数增加了 15,因此每组从 15 开始。

如果我从列表的前面开始并取数字,我会得到一个这样的组

原始列表还剩下什么:240、130、180、140、225、85 总共剩余 1000 个

第 1 组:15、100、115、105、205、195、240 共 975

剩余的数量是1000,当下一次递归尝试做第二个1000组时,会留下85,导致失败。

所以算法是回到第 1 组,(第二组迭代的“进度”现在消失了),删除最后一个数字,然后开始查看剩余的列表以找到下一个适合的第一个数字。

在这种情况下,组 1 中的最后 240 个将被删除,并替换为列表中的下一个 240,因此下一个组 2 迭代将再次失败。

因此,从第 2 组的迭代中删除“进度”,返回第 1 组并删除 240。现在第 1 组,其余看起来像这样

剩余:240、240、130、180、140、225、85

第 1 组:15、100、115、105、205、195

下一次迭代应该取 130,然后是 85,这将组成一组 950,所以剩下的就是 1025,再一次不适合了。

等等等等。我遇到的问题是有一个递归级别知道它已经尝试过哪些数字并知道要避免它们,而下一次迭代不会避免前一个迭代避免的那些。当第 1 组从其列表中删除 240 并将剩余的返回给它时,当第 2 组开始从列表中挑选时,它将以 240 开头,因为它将是列表中的第一个

这个列表最终的解决方案是

第 1 组:15、100、115、105、205、195、180、85

第 2 组:15、240、240、130、140、225

【问题讨论】:

  • 如果我理解正确你在做什么,那么你可能不需要从列表中物理删除该项目,但你可以有一个指向你的“当前”元素的索引重新合作。并且索引之前的所有元素都可以认为是移除了
  • 考虑分享您尝试过的代码,并在说明问题时引用代码行。它可能会提高您收到的答案的质量。 (并不是说当前的答案不好;只是他们不得不在没有更多信息的情况下猜测问题。)

标签: c# recursion pass-by-reference bin-packing


【解决方案1】:

您可以在调用递归函数时尝试克隆列表并传递新创建的克隆而不是原始列表。这可能看起来像这样:

public List<int> RecursiveFunction(List<int> listOfRemainingNumbers)
{
    // Do some logic
    List<int> numbers = new List<int>();
    List<int> clone = new List<int>(numbers);
    return RecursiveFunction(clone);
}

请注意,这并不是一种真正有效的方法。特别是当您的列表非常大并且包含数千个项目时,这种方法将使用大量内存。 一种更有效的方法可能是不使用递归,而是使用简单的循环,并尽量不从列表中删除项目,可能使用out 关键字从您的函数中获取额外的“返回值”。

【讨论】:

    【解决方案2】:

    你是不是太努力了?或者你可能不熟悉Linq,它非常强大......

    List<int> n = new List<int>() { 432, 12398, 38, 438, 865, 2, 38, 716, 9421, 347, 550 };
    var n2 = n.OrderBy(num => num).ToList();
    

    确保添加到代码的顶部...

    using System.Linq;
    

    您可能会惊讶于它返回列表的速度有多快,而无需您控制任何递归或拆分为辅助组。

    【讨论】:

    • 小组实际上是目标。如果要求额外帮助不是太多,我编辑了原始问题。不过谢谢
    猜你喜欢
    • 2023-01-10
    • 1970-01-01
    • 2016-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-23
    • 2010-10-25
    相关资源
    最近更新 更多