📜  动态编程递归基本案例 (1)

📅  最后修改于: 2023-12-03 15:37:00.505000             🧑  作者: Mango

动态编程递归基本案例

动态编程和递归是常用于解决计算机程序中的问题的两种方法。动态编程使用“记忆化”技术将计算结果存储在数组中,以便后续访问。而递归则是一个函数调用自身的过程。

在这篇文章中,我们将讨论一些基本的动态编程递归案例。这些案例包括计算斐波那契数列、计算乘积、计算编辑距离等。

斐波那契数列

斐波那契数列是指前两个数是1,从第三个数开始,每个数都是前两个数之和。数列的前几项为 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, ...

我们可以使用递归方法计算斐波那契数列。该方法的代码如下:

def fib(n):
    if n <= 0:
        return 0
    elif n == 1:
        return 1
    else:
        return fib(n-1) + fib(n-2)

这个递归函数将会在计算斐波那契数列中的每个数字时,调用自身两次。这意味着,在计算较高斐波那契数时,计算机将执行大量的重复计算。此时,使用动态编程技术将会大大提高程序的效率。

为了使用动态编程技术计算斐波那契数列,我们可以使用一个数组来存储已经计算出来的数列中的数字。每次计算一个新的数字时,我们先在数组中查找该数字是否已经计算过。如果找到了,我们直接返回该数字即可。否则,我们使用递归的方式计算该数字,将其添加到数组中,并将其返回。

下面的代码演示了如何使用动态编程技术计算斐波那契数列:

def fib(n, memo={}):
    if n <= 0:
        return 0
    elif n == 1:
        return 1

    if n in memo:
        return memo[n]

    memo[n] = fib(n-1, memo) + fib(n-2, memo)
    return memo[n]
计算乘积

给定一个集合,计算其所有元素的乘积。例如,给定集合 {3, 5, 2, 7},计算出它们所有元素的乘积 3 * 5 * 2 * 7 = 210。

使用递归计算乘积的方法如下:

def prod(values):
    if len(values) == 0:
        return 1
    else:
        return values[0] * prod(values[1:])

这个方法将递归调用自身,以便计算集合中的每个元素。然而,它会在计算过程中重复执行大量的计算。为了解决这个问题,我们可以使用动态编程技术将已经计算过的结果存储在数组中,并在需要时直接使用。

下面的代码演示了如何使用动态编程技术计算乘积:

def prod(values, memo={}):
    if len(values) == 0:
        return 1

    key = tuple(values)
    if key in memo:
        return memo[key]

    result = values[0] * prod(values[1:], memo)
    memo[key] = result
    return result
计算编辑距离

编辑距离用于衡量两个字符串的相似程度。编辑距离是通过将一个字符串转换为另一个字符串所需的最少操作次数来度量的,其中操作可以是插入、删除和替换操作。

例如,假设有两个字符串“kitten”和“sitting”。我们将“kitten”转换为“sitting”需要执行以下三种操作:将“k”替换为“s”,将“e”替换为“i”,将“n”插入为“g”。因此,它们之间的编辑距离为 3。

我们可以使用递归方法计算编辑距离。该方法的代码如下:

def edit_distance(s1, s2):
    if len(s1) == 0:
        return len(s2)
    elif len(s2) == 0:
        return len(s1)

    if s1[0] == s2[0]:
        return edit_distance(s1[1:], s2[1:])
    else:
        add = edit_distance(s1, s2[1:])
        remove = edit_distance(s1[1:], s2)
        replace = edit_distance(s1[1:], s2[1:])

        return 1 + min(add, remove, replace)

该函数将使用四种操作中的一种来将字符串s1转换为s2。在计算编辑距离时,该函数将执行大量的重复计算。因此,使用动态编程技术将会大大提高程序的效率。

为了使用动态编程技术计算编辑距离,我们可以使用一个二维数组来存储已经计算过的结果。每次计算编辑距离时,我们先在数组中查找该值是否已经计算过。如果找到了,我们直接返回该值。否则,我们使用递归的方式计算该值,并将其添加到数组中。

下面的代码演示了如何使用动态编程技术计算编辑距离:

def edit_distance(s1, s2, memo={}):
    if len(s1) == 0:
        return len(s2)
    elif len(s2) == 0:
        return len(s1)

    key = (s1, s2)
    if key in memo:
        return memo[key]

    if s1[0] == s2[0]:
        result = edit_distance(s1[1:], s2[1:], memo)
    else:
        add = edit_distance(s1, s2[1:], memo)
        remove = edit_distance(s1[1:], s2, memo)
        replace = edit_distance(s1[1:], s2[1:], memo)
        result = 1 + min(add, remove, replace)

    memo[key] = result
    return result
总结

本文介绍了三个基本的动态编程递归案例,包括计算斐波那契数列、计算乘积、计算编辑距离。这些案例展示了如何使用递归方法来解决计算机程序中的问题,并展示了如何使用动态编程技术提高程序的效率。在实际开发中,我们需要根据具体问题的需要选择合适的算法和数据结构,以便编写出高效和可靠的程序。