【问题标题】:Describe array transition with specific commands使用特定命令描述数组转换
【发布时间】:2018-07-25 15:14:31
【问题描述】:

假设我们有两个整数数组,例如:

var A = new int[] {1, 4, 6, 12, 44};
var B = new int[] {2, 4, 6, 44, 45};

问题是将转换步骤描述为:

从数组A开始,继续如下:

  • 第 1 步:remove index = 0 // result = {4, 6, 12, 44}
  • 第 2 步:insert index = 0 value = 2 // result = {2, 4, 6, 12, 44}
  • 第 3 步:remove index = 3 // result = {2, 4, 6, 44}
  • 第 4 步:insert index = 4 value = 45 // result = {2, 4, 6, 44, 45}

我们现在有了数组B

我的问题是:如何使用任何编程语言或伪代码来设计此算法,以便为给定的数组 A 和 B 以编程方式生成这些步骤?

常见的步骤结构如下:

第 N 步:insert/remove index = i [value = v]

当然,从A 中删除所有元素,然后从B 中插入所有元素是一种解决方案,对于给定的AB,可能会有不止一个解决方案,但我正在寻找以最少的步骤进行过渡。

【问题讨论】:

    标签: c# arrays algorithm


    【解决方案1】:

    Levenshtein distance 的概念。它用于比较两个字符串(但是您也可以将相同的原则应用于整数数组):将一个字符串更改为另一个字符串的最少编辑次数,其中一次编辑是删除、插入或替换。

    使用动态规划可以有效地解决问题。 wiki 文章展示了这种方法。 您可以对您的问题使用相同的方法。但是由于在您的情况下您不允许替换元素(仅删除和插入操作),您甚至可以简化递归(微小)位:

    def edit_distance(s, len_s, t, len_t):
        if len_s == 0:
           return len_t
        if len_t == 0:
           return len_s
    
        if s[len_s-1] == t[len_t-1]:
            return edit_distance(s, len_s-1, t, len_t-1)
        else:
            return min(edit_distance(s, len_s-1, t, len_t) + 1, 
                       edit_distance(s, len_s, t, len_t-1) + 1)
    

    上面的代码没有动态编程。为了提高效率,您需要添加它。

    此外,代码只会计算步数。如果您还想列出步骤,则必须存储完整的表格并回溯解决方案。

    该方法的时间和内存复杂度:O(len_s * len_t)。


    这是一个使用您的两个数组[1, 4, 6, 12, 44][2, 4, 6, 44, 45] 的示例。如果您对字符串的每个可能的前缀组合应用动态编程(例如,使用底部优先方法),您会得到一个表格。

    0 1 2 3 4 5 
    1 2 3 4 5 6 
    2 3 2 3 4 5 
    3 4 3 2 3 4 
    4 5 4 3 4 5 
    5 6 5 4 3 4 
    

    在右下角,我们看到 4 是使两个数组相等的最佳步数。现在我们可以回溯并再次查看递归公式。由于最后两个元素不相等,因此它必须是插入/删除操作。我们可以在表格中看到[1, 4, 6, 12], [2, 4, 6, 44, 45] 的最佳步数是5[1, 4, 6, 12, 44], [2, 4, 6, 44] 的最佳步数是3。所以这里的最佳做法是删除第二个数组的最后一个元素,或者换句话说,在第一个数组中插入45

    现在我们可以处理导致[1, 4, 6, 12, 44], [2, 4, 6, 44] 的最后一步。由于最后一个元素相等,因此步骤很清楚。我们将它们都留下,不执行插入或删除操作。

    那么[1, 4, 6, 12], [2, 4, 6] 的最后一步是什么?从表中可以看出,最优值 3 来源于[1, 4, 6], [2, 4, 6] 的位置,这意味着在第一个数组中删除了12

    等等。

    有趣的是,可以有多个最佳解决方案。在这里,我向您展示了一种可能的路径(与您的解决方案完全对应):

    0-1 2 3 4 5 
      |       
    1 2 3 4 5 6 
       \      
    2 3 2 3 4 5 
         \    
    3 4 3 2 3 4 
          |   
    4 5 4 3 4 5 
           \  
    5 6 5 4 3-4 
    

    【讨论】:

    • 让我们假设我们包含了替换,并使用 Levenshtein 距离算法找到了步数。例如,我们如何暴力破解解决方案的 3 个步骤?请分享如果您有任何想法 Bcs 可以说我们发现需要 1 个插入、1 个更新、1 个删除操作。然后我们可以暴力删除操作,但不能使用插入操作 bcs 我们需要知道要插入/更新什么
    • @RaminRahimzada 我在解释中添加了一个示例。注意:我的实现仍然没有使用 DP(虽然它只有 1-2 行代码)。所以如果你不熟悉动态规划,你应该先学习一下。这实际上是一个非常经典的问题,你会在几乎每一门基本算法课程中找到它。
    猜你喜欢
    • 2019-10-07
    • 2012-05-30
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-25
    • 2011-09-02
    • 1970-01-01
    相关资源
    最近更新 更多