分析python动态规划的递归、非递归实现

针对“分析Python动态规划的递归、非递归实现”这个主题,我将分为以下几个部分进行完整的讲解。

1. 什么是动态规划

动态规划(Dynamic Programming)是一种通过把原问题分解为相对简单的子问题的方式,以递推的方式求解复杂问题的技术。在动态规划中,我们通常会用到“备忘录”或“DP表”来记录以前求解过的值,从而避免重复计算,提高程序效率。

动态规划的应用场景十分广泛,比如求最长公共子序列、背包问题、图像压缩等等。在刷LeetCode等编程题目的时候,也经常会用到。

2. 动态规划的递归实现

下面我以求解斐波那契数列为例,来详细讲解动态规划的递归实现。

2.1 斐波那契数列的定义

斐波那契数列是一个数学上比较经典的数列,它的定义如下:

F[0] = 0

F[1] = 1

F[i] = F[i-1] + F[i-2],(i>=2, i∈N*)

2.2 递归实现

先来看一下斐波那契数列的递归实现:

def fib(n):
    # base case
    if n == 0 or n == 1:
        return n
    # recursive case
    return fib(n-1) + fib(n-2)

在这个递归实现中,我们首先判断了n是否为0或1,如果是的话就直接返回n,否则就递归调用fib(n-1)和fib(n-2),并将它们的和返回。

递归实现的优点在于代码简洁易懂,但它的缺点也很明显,那就是会进行大量的重复计算。比如计算fib(5)的时候,fib(4)和fib(3)都会被计算一次,而计算fib(4)的时候,fib(3)还会被计算一次,这样就会浪费很多时间,效率较低。

3. 动态规划的非递归实现

了解了动态规划的递归实现之后,我们接下来来看一下非递归实现。

3.1 状态存储

使用动态规划进行求解时,我们通常需要定义一些状态,并将它们保存下来。在斐波那契数列的求解中,我们可以定义一个长度为n+1的数组dp来存储每一项的值,其中dp[i]就表示第i个斐波那契数列的值。

3.2 非递归实现

下面是斐波那契数列的非递归实现:

def fib(n):
    # base case
    if n == 0 or n == 1:
        return n

    dp = [0] * (n+1)
    dp[0], dp[1] = 0, 1

    for i in range(2, n+1):
        dp[i] = dp[i-1] + dp[i-2]

    return dp[n]

在这个非递归实现中,我们首先判断n是否为0或1,如果是的话就直接返回n。然后我们定义一个数组dp,并将第0个和第1个元素的值分别赋为0和1。接下来我们通过循环从2开始计算每个斐波那契数列的值,通过dp[i-1]和dp[i-2]的值相加来得到dp[i]的值。最后返回dp[n]即可。

4. 示例说明

在实际编程中,我们常常需要使用动态规划来解决问题。下面通过两个例子来加深对动态规划的理解。

4.1 求解最长递增子序列

假设我们有一个长度为n的序列a,请问它的最长递增子序列(LIS)是多长?

我们可以通过动态规划来解决这个问题。我们定义数组dp,其中dp[i]表示以第i个数结尾的最长递增子序列的长度。那么dp[i]的值怎么求呢?

当a[j] < a[i]时,我们可以将dp[i]设置为dp[j] + 1,因为此时可以将a[j]加入到以a[i]为结尾的最长递增子序列中。而当a[j] >= a[i]时,我们就不能将a[j]加入到以a[i]为结尾的最长递增子序列中了,此时dp[i]的值就不变。

最后,我们只需要遍历一遍a数组,求出所有的dp[i],再取其中的最大值,就是最长递增子序列的长度。

下面是求最长递增子序列的Python代码:

def lengthOfLIS(nums):
    n = len(nums)
    if n == 0:
        return 0
    dp = [1] * n
    for i in range(1, n):
        for j in range(i):
            if nums[j] < nums[i]:
                dp[i] = max(dp[i], dp[j] + 1)
    return max(dp)

4.2 求解最大子序和

给定一个长度为n的整数序列a,请你找出其中的一个连续子序列,使得它的和最大。其中,序列元素不允许为空。

我们可以通过动态规划来解决这个问题。我们定义数组dp,其中dp[i]表示以第i个数结尾的最大子序和。那么dp[i]的值怎么求呢?

当dp[i-1] > 0时,dp[i] = dp[i-1] + a[i],表示以a[i]为结尾的连续子序列一定包含a[i-1],因此可以将a[i]添加进去。而当dp[i-1] <= 0时,dp[i] = a[i],表示以a[i]为结尾的连续子序列只包含a[i]本身。

最后,我们只需要遍历一遍a数组,求出所有的dp[i],再取其中的最大值,就是最大子序和。

下面是求解最大子序和的Python代码:

def maxSubArray(nums):
    n = len(nums)
    dp = nums.copy()
    for i in range(1, n):
        dp[i] = max(dp[i], dp[i-1] + nums[i])
    return max(dp)

5. 总结

本文从动态规划的定义入手,详细讲解了动态规划的递归实现和非递归实现,并通过两个示例说明加深了对动态规划的理解。动态规划是一种非常有用的算法,掌握了它可以让我们在实际编程中事半功倍。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:分析python动态规划的递归、非递归实现 - Python技术站

(0)
上一篇 2023年5月26日
下一篇 2023年5月26日

相关文章

  • java和jsp之间的request传值方法

    介绍Java和JSP之间的request传值方法,主要有三种:参数,属性和Session。 1. 参数 使用参数的方法最为简单,只需要在传值的时候,将值通过URL的参数形式传递过去即可。JSP页面中获取参数值的方法是通过request.getParameter()方式。 示例1:将参数id传递给另一个JSP页面 <a href="page2.…

    Java 2023年6月15日
    00
  • Java的Struts框架报错“ActionMappingException”的原因与解决办法

    当使用Java的Struts框架时,可能会遇到“InvalidTokenException”错误。这个错误通常由以下原因之一起: 令牌无效:如果令牌无,则可能会出现此错误。在这种情况下,需要检查令牌是否有效以解决此问题。 配置错误:如果配置文件中正确配置,则可能会现此错误。在这种情况下,检查文件以解决此问题。 以下是两个实例: 例 1 如果令牌无效,则可以尝…

    Java 2023年5月5日
    00
  • 使用JDBC工具类实现简单的登录管理系统

    使用JDBC工具类实现简单的登录管理系统需要以下步骤: 准备工作 在项目中引入JDBC依赖,如使用Maven引入jdbc依赖: <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> &l…

    Java 2023年6月16日
    00
  • Spring Boot之FilterRegistrationBean-自定义Filter详解

    下面是对于“Spring Boot之FilterRegistrationBean-自定义Filter详解”的完整攻略。 什么是FilterRegistrationBean? FilterRegistrationBean是Spring提供的一个Bean,用于将Filter(过滤器)注册到Servlet容器中的过程中进行拦截,进而实现自定义Filter。 如何使…

    Java 2023年5月31日
    00
  • SprintBoot深入浅出讲解场景启动器Starter

    SprintBoot深入浅出讲解场景启动器Starter 什么是场景启动器 Starter? 在 Spring Boot 中,Starter 是一种约定俗成的方式,可以将基础依赖项捆绑在一起,从而快速引导应用程序进入不同的场景。场景启动器通常使用以下命名约定:spring-boot-starter-* 。例如, spring-boot-starter-web…

    Java 2023年5月19日
    00
  • 如何用Java实现排列组合算法

    下面是关于如何用Java实现排列组合算法的完整攻略: 排列组合算法实现 什么是排列与组合 排列是指选出m个元素,一次排成一个列,有序的称为$m$的排列,记为$A_m^n$ 组合是指选出m个元素,无序的称为${m}$的组合,记作$C_m^n$ 可以发现,排列与组合的关联非常大,在代码实现中,它们也是联系在一起的。 排列算法实现 递归算法 通过递归实现简单,下面…

    Java 2023年5月19日
    00
  • jsp Request获取url信息的各种方法对比

    JSP Request获取URL信息的各种方法对比 当我们在JSP文件中需要获取URL信息时,可以使用多种方式,本文将对比一下常用的几种方法。 request.getRequestURL() request.getRequestURL() 方法可以获取当前请求的URL。 示例: <% String url = request.getRequestURL…

    Java 2023年6月15日
    00
  • Java实现考试系统

    Java实现考试系统攻略 概述 本文介绍如何使用Java实现一个考试系统。该系统包含了以下功能: 单选题和多选题的创建和管理 考试试卷生成和管理 学生考试、交卷和阅卷 系统设计 数据库设计 考试系统需要存储题目、试卷和学生等信息。因此需要设计以下表格: question 表:用于存储题目信息,包括题目内容、选项和正确答案等。 exam 表:用于存储试卷信息,…

    Java 2023年5月19日
    00
合作推广
合作推广
分享本页
返回顶部