iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >动态规划详解Python
  • 513
分享到

动态规划详解Python

动态规划python代理模式 2023-09-09 12:09:14 513人浏览 安东尼

Python 官方文档:入门教程 => 点击学习

摘要

动态规划 动态规划(Dynamic Programming)是一种用于解决复杂问题的算法设计方法。它通常用于优化问题,其中问题可以被分解成一系列重叠子问题,通过存储并重复使用已经解决过的子问题的解,可

动态规划

动态规划(Dynamic Programming)是一种用于解决复杂问题的算法设计方法。它通常用于优化问题,其中问题可以被分解成一系列重叠子问题,通过存储并重复使用已经解决过的子问题的解,可以避免重复计算,从而提高算法的效率。

动态规划的基本思想是将原始问题分解成若干个子问题,并逐个求解这些子问题的最优解。通过定义状态和状态转移方程,可以将问题的求解转化为一个递推过程,从而得到最优解。

动态规划算法的核心步骤通常包括以下几个方面:

  1. 定义问题的状态:将原始问题抽象为一个或多个子问题,并定义状态来表示子问题的解。
  2. 确定状态转移方程:通过分析子问题之间的关系,建立状态之间的转移方程,描述当前状态和之前状态之间的关系。
  3. 确定初始条件:确定最简单的子问题的解,即初始状态的值。
  4. 递推求解:使用状态转移方程和初始条件,逐步计算出更复杂的子问题的解,直到得到原始问题的解。
  5. 解析解:根据子问题的解,逐步还原出原始问题的解。

动态规划算法通常具有较高的时间复杂度,但通过存储已解决的子问题的解,可以大大减少重复计算,提高算法效率。它在许多领域有广泛的应用,如组合优化、图论、序列比对、路径规划等。

斐波那契数列

这里简单的解释一下斐波那契数列:F(0) = 0 , F(1) = 1
F(N) = F(N-1) + F(N-2) , N>1 数列前几项如下:
0 1 1 2 3 5 8 13 21…

递归代码和非递归代码比较

import timedef calculate_time(func):    def wrapper(*args, **kwargs):        start_time = time.time()        result = func(*args, **kwargs)        end_time = time.time()        execution_time = end_time - start_time        print(f"函数 {func.__name__} 的执行时间为:{execution_time} 秒")        return result    return wrapper@calculate_timedef func1(n):    return _func1(n)# 存在大量的子问题重复计算def _func1(n):    if n <= 1:        return n    return _func1(n - 1) + _func1(n - 2)# 把需要用到的子问题存起来@calculate_timedef func2(n):    f = [0, 1]    if n > 1:        for i in range(n - 1):            num = f[-1] + f[-2]            f.append(num)    return f[n]print(func1(36))print(func2(36))

运行结果:
函数 func1 的执行时间为:3.150125503540039 秒
14930352
函数 func2 的执行时间为:0.0 秒
14930352

爬楼梯

问题:有一个楼梯,总共有10级台阶,每次只能走一级或者两级台阶,全部走完,有多少种走法?

找规律得到递推式:
在这里插入图片描述

def climbStairs(self, n: int) -> int:    f = [0,1,2]    if n > 2:        for i in range(n-2):            r = f[-1] + f[-2]            f.append(r)    return f[n]

最大回撤

问题:有一个数组,求其中两个数x,y,满足x的索引小于y的索引,使得 x-y 最大。例如 arr = [3,7,2,6,4,1,9,8,5], 最大回撤是6,对应的x=7,y=1。

初始时,设max_drop=0,peak都设为arr[0]。然后从左到右遍历数组,对于每个元素price:

  1. 如果price大于peak,更新peak为当前的price。
  2. 否则,计算当前的回撤值drop,即peak - price。
  3. 如果drop大于max_drop,更新max_drop为当前的drop。

最终,max_drop就是最大回撤的值。

# 只返回最大回撤的金额def calculate_max_drawdown(arr):    max_drop = 0    peak = arr[0]    for i in range(1, len(arr)):        if arr[i] > peak:            peak = arr[i]        else:            drop = peak - arr[i]            if drop > max_drop:                max_drop = drop    return max_drop# 示例用法arr = [3, 7, 2, 6, 4, 1, 9, 8, 5]max_drawdown = calculate_max_drawdown(arr)print(max_drawdown)  # 输出: 6

要求计算出最大回撤,并且对应的返回x和y
可以使用动态规划的思想来解决这个问题。我们可以定义一个变量max_sum来跟踪当前的最大子数组和,以及一个变量current_sum来记录当前的子数组和。

初始时,将max_sum和current_sum都设为数组中的第一个元素。然后从数组的第二个元素开始遍历,对于每个元素num:

  1. 将current_sum与0比较,取其中较大的值,并将num加到current_sum中,得到新的current_sum。
  2. 将current_sum与max_sum比较,取其中较大的值,并将结果赋给max_sum。

最终,max_sum就是最大连续子数组的和。

def calculate_max_drawdown(arr):    max_drop = 0    peak = 0    start_index = 0    end_index = 0    for i, price in enumerate(arr):        if price > peak:            peak = price        else:            drop = peak - price            if drop > max_drop:                max_drop = drop                start_index = arr.index(peak)                end_index = i    return max_drop, start_index, end_index# 示例用法arr = [3, 7, 2, 6, 4, 1, 9, 8, 5]max_drawdown, start_index, end_index = calculate_max_drawdown(arr)print("最大回撤:", max_drawdown)print("起始索引:", start_index)print("结束索引:", end_index)

输出:
最大回撤: 6
起始索引: 1
结束索引: 4

最大连续子数组和

问题:给定一个数组,求其最大连续子数组的和。例如:arr = [1,5,-10,2,5,-3,2,6,-3,1]. 输出为:12。对应的连续子数组为 [2,5,-3,2,6]。

def max_subarray_sum(arr):    max_sum = arr[0]    current_sum = arr[0]    for num in arr[1:]:        current_sum = max(num, current_sum + num)        max_sum = max(max_sum, current_sum)    return max_sum# 示例用法arr = [1, 5, -10, 2, 5, -3, 2, 6, -3, 1]max_sum = max_subarray_sum(arr)print(max_sum)  # 输出: 12
"""同时输出对应的子数组"""def max_subarray_sum(arr):    max_sum = arr[0]    current_sum = arr[0]    start_index = 0    end_index = 0    temp_start_index = 0    for i, num in enumerate(arr[1:], start=1):        if num > current_sum + num:            temp_start_index = i            current_sum = num        else:            current_sum = current_sum + num        if current_sum > max_sum:            start_index = temp_start_index            end_index = i            max_sum = current_sum    subarray = arr[start_index:end_index + 1]    return max_sum, subarray# 示例用法arr = [1, 5, -10, 2, 5, -3, 2, 6, -3, 1]max_sum, subarray = max_subarray_sum(arr)print("最大连续子数组和:", max_sum)print("最大连续子数组:", subarray)

输出:
最大连续子数组和: 12
最大连续子数组: [2, 5, -3, 2, 6]

最长不重复子串

题目形式:给定一个字符串,找出没有重复字符的最长的子串。例如输入“abcbefgf”,答案是 “cbefg”。

算法步骤如下:

  1. 定义两个指针,start 和 end,分别表示滑动窗口的起始位置和

  2. 结束位置,初始时两个指针都指向字符串的开头。

  3. 定义一个集合 seen,用于存储滑动窗口中出现过的字符。

  4. 定义两个变量 max_length 和 max_substring,分别用于记录最长子串的长度和内容,初始时都为 0。开始遍历字符串,从左到右依次移动 end 指针:
    —a.如果当前字符 s[end] 在集合 seen 中不存在,说明是一个新的字符,将其加入 seen 中,并更新 end 指针。
    —b.如果当前字符 s[end] 在集合 seen 中已经存在,说明遇到了重复字符。此时需要移动 start 指针,并更新 seen 集合,直到滑动窗口中不再有重复字符。

    —c.在每次移动 end 指针时,都需要更新 max_length 和 max_substring,以记录当前的最长子串。

  5. 遍历结束后,返回最长子串 max_substring。

def longest_unique_substring(s):    start = 0    end = 0    seen = set()    max_length = 0    max_substring = ""    while end < len(s):        if s[end] not in seen:            seen.add(s[end])            end += 1        else:            if end - start > max_length:                max_length = end - start                max_substring = s[start:end]            seen.remove(s[start])            start += 1    if end - start > max_length:        max_substring = s[start:end]    return max_substring# 示例用法s = "abcbefgf"result = longest_unique_substring(s)print(result)  # 输出: "cbefg"

全排列

问题:给定一个数组,找出其所有可能的排列。例如: arr = [1,1,3],输出为 [[1,1,3],[1,3,1],[3,1,1]]。

def permute_unique(nums):    # 定义递归函数,生成给定位置上的所有可能排列    def backtrack(start):        # 终止条件:当遍历到数组末尾时,将当前生成的排列加入结果集        if start == len(nums):            permutations.append(nums[:])  # 将当前排列加入结果集            return        # 使用一个集合来记录已经选择过的元素,避免重复生成相同的排列        used = set()        # 从当前位置开始,依次尝试每个元素作为当前位置的元素        for i in range(start, len(nums)):            # 如果当前元素已经被选择过,则跳过            if nums[i] in used:                continue            # 进行选择:将当前元素加入路径,并标记为已选择            used.add(nums[i])            nums[start], nums[i] = nums[i], nums[start]            # 递归调用自身,在新的位置上生成剩余元素的所有可能排列            backtrack(start + 1)            # 撤销选择:将当前选择的元素从路径中移除,并将其标记为未选择,以便进行下一次选择            nums[start], nums[i] = nums[i], nums[start]            used.remove(nums[i])    permutations = []  # 结果集,用于存储所有排列    backtrack(0)  # 从位置0开始生成所有排列    return permutations# 示例用法nums = [1, 1, 3]result = permute_unique(nums)print(result)

快速排序+二分查找

def partition(lst, left, right):    temp = lst[left]    while left < right:        while left < right and lst[right] >= temp:            right -= 1        lst[left] = lst[right]        while left < right and lst[left] <= temp:            left += 1        lst[right] = lst[left]    lst[left] = temp    return leftarr = [5, 2, 8, 6, 3]print(partition(arr, 0, len(arr) - 1))def quick_sort(lst, left, right):    if left < right:        mid = partition(lst, left, right)        quick_sort(lst, left, mid)        quick_sort(lst, mid + 1, right)quick_sort(arr, 0, len(arr) - 1)print(arr)#  二分查找只适用于在有序序列中查找元素def binary_search(lst, val):    left = 0    right = len(lst) - 1    while left <= right:        mid = (left + right) // 2        if lst[mid] == val:            return mid        elif lst[mid] > val:  # 说明要查找的值在mid的左边            right = mid - 1        else:  # 说明要查找的值在mid的右边、            left = mid + 1    # 代码执行至此说明没有找到元素val,返回-1    return -1# 注意:mid定义在while循环里面print(binary_search(arr, 8))

输出:
2
[2, 3, 5, 6, 8]
4

合并两个有序数组(归并排序)

题目形式:给定两个按升序排列的有序数组,将它们合并成一个新的有序数组。例如:a = [1,2,6,8], b = [2,4,7,10],输出为 arr = [1,2,2,4,6,7,8,10]

# 定义合并函数,将两个有序序列合并为一个有序序列def merge(lst, left, mid, right):    """    思路:定义一个列表merged,循环比较两个有序序列的首元素大小,并放入临时空列表。    """    if left < right:        merged = []        i = left        j = mid + 1        while i <= mid and j <= right:            if lst[i] < lst[j]:                merged.append(lst[i])                i += 1            else:                merged.append(lst[j])                j += 1        # 代码执行至此,有一个序列元素为空,另一个不为空,接下来将剩下的元素放入空列表        while i <= mid:            merged.append(lst[i])            i += 1        while j <= right:            merged.append(lst[j])            j += 1        lst[left:right + 1] = merged        return lstdef _merge_sort(lst, left, right):    if left < right:        mid = (left + right) // 2        _merge_sort(lst, left, mid)        _merge_sort(lst, mid + 1, right)        merge(lst, left, mid, right)@calculate_timedef merge_sort(lst):    _merge_sort(lst, 0, len(lst) - 1)if __name__ == '__main__':    # 测试代码    lst = list(range(10000))    random.shuffle(lst)    print(lst)    merge_sort(lst)    print(lst)

三数之和

def sum_of_three(arr,target):    assert len(arr)>=3,"len(arr) should >=3!"    arr.sort()    ans = set()    for k,c in enumerate(arr):        i,j = k+1,len(arr)-1        while i<j:            if arr[i]+arr[j]+c <target:                i = i+1            elif arr[i]+arr[j]+c > target:                j = j-1            else:                ans.update({(arr[k],arr[i],arr[j])})                i = i+1                j = j-1    return(list(ans)) print(sum_of_three([-3,-1,-2,1,2,3],0))

来源地址:https://blog.csdn.net/qq_34184505/article/details/131415306

--结束END--

本文标题: 动态规划详解Python

本文链接: https://www.lsjlt.com/news/401478.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 动态规划详解Python
    动态规划 动态规划(Dynamic Programming)是一种用于解决复杂问题的算法设计方法。它通常用于优化问题,其中问题可以被分解成一系列重叠子问题,通过存储并重复使用已经解决过的子问题的解,可...
    99+
    2023-09-09
    动态规划 python 代理模式
  • Python之动态规划
    序言 最近在学习python语言,语言有通用性,此文记录复习动态规划并练习python语言。 动态规划(Dynamic Programming) 动态规划是运筹学的一个分支,是求解决策过程最优化的过程。20世纪50年代初,美国数学家贝尔曼(...
    99+
    2023-08-30
    python 动态规划
  • C语言动态内存规划详解
    目录动态内存规划动态内存函数的介绍总结动态内存规划 用C语言写程序时,因为语言的一些特性使用数组的时候只能用常量来申明数组,就导致数组的内存被卡得很死,不能根据我们的实际需求灵活的使...
    99+
    2024-04-02
  • C++实现动态规划过程详解
    目录C++实现动态规划1. 动态规划的基础2. 动态规划的实现方法3. 实际应用C++实现动态规划 动态规划是解决一类最优问题的常用方法,它是解决最优化问题的一种途径,因为这种算法通...
    99+
    2023-05-20
    C++实现动态规划 C++动态规划
  • python动态规划算法怎么用
    小编给大家分享一下python动态规划算法怎么用,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!python有哪些常用库python常用的库:1.requesuts;2.scrapy;3.pillow;4.twisted;5...
    99+
    2023-06-14
  • C语言动态规划之背包问题详解
    01背包问题        给定n种物品,和一个容量为C的背包,物品i的重量是w[i],其价值为v[i]。问如何选择装入背包的物品,使得装入背...
    99+
    2024-04-02
  • 什么是动态规划
    这篇文章主要介绍“什么是动态规划”,在日常操作中,相信很多人在什么是动态规划问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”什么是动态规划”的疑惑有所帮助!接下来,请跟着小编一...
    99+
    2024-04-02
  • 60题学会动态规划系列:动态规划算法第三讲
    简单多状态问题 文章目录 一.按摩师二.打家劫舍系列三.删除并获得点数四.粉刷房子 1.按摩师 力扣链接:力扣 一个有名的按摩师会收到源源不断的预约请求,每个预约都可以选择接或不接。在每次预约服务之间要有休息时间,因...
    99+
    2023-10-05
    c++ 后端 算法 动态规划 力扣
  • C++ 函数递归详解:动态规划中的递归
    摘要:递归调用在 c++++ 中通过调用自身的函数实现。斐波那契数列的递归求解需要三个组成部分:基础条件(n 小于等于 1)、递归调用(自身求解 f(n-1) 和 f(n-2))、递增/...
    99+
    2024-05-03
    c++ 递归
  • Python算法题解:动态规划解0-1背包问题
    概述背包问题(Knapsack problem)是一种组合优化的NP完全问题。问题可以描述为:给定一组物品,每种物品都有自己的重量和价格,在限定的总重量内,我们如何选择,才能使得物品的总价格最高。问题的名称来源于如何选择最合适的物品放置于给...
    99+
    2023-06-02
  • Python最大连续区间和动态规划
    be前言:期末临近,考Python的同学可以练练 问题描述:给定一段长度为N的整数序列A,请从中选出一段连续的子序列(可以为0)使得这段的总和最大 这里就不提暴力法了,只能在OJ系...
    99+
    2024-04-02
  • Python算法思想集结深入理解动态规划
    目录1. 概述什么是重叠子问题动态规划与分治算法的区别什么最优子结构2. 流程2.1 是否存在子问题2.2 是否存在重叠子问题怎么解决重叠子问题2.3 状态转移3.总结1. 概述 动...
    99+
    2024-04-02
  • LeetCode 动态规划之矩阵区域和详情
    目录题目题解解题分析解题代码题目 矩阵区域和 给你一个 m x n 的矩阵 mat 和一个整数 k ,请你返回一个矩阵&n...
    99+
    2024-04-02
  • c++动态规划经典算法
    目录基本思想重要分析问题方法动态规划算法实例1、台阶问题2、从矩阵左上角走到右下角最短路径问题3、最大子数组问题4、最长公共子序列基本思想    &nb...
    99+
    2024-04-02
  • C++编辑距离(动态规划)
    题目描述: 给你两个单词 word1 和 word2,请你计算出将 word1 转换成 word2 所使用的最少操作数 。 我们可以对一个单词进行如下三种操作: 插入一个字符删除一个...
    99+
    2024-04-02
  • java中什么是动态规划
    这篇文章给大家介绍java中什么是动态规划,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。java基本数据类型有哪些Java的基本数据类型分为:1、整数类型,用来表示整数的数据类型。2、浮点类型,用来表示小数的数据类型。...
    99+
    2023-06-14
  • 【动态规划】背包问题(详细总结,很全)
    【动态规划】 一、 背包问题1. 背包问题总结1)动规四部曲:2) 递推公式总结:3) 遍历顺序总结: 2. 01背包1) 二维dp数组代码实现 2) 一维dp数组代码实现 ...
    99+
    2023-09-09
    动态规划 算法 python leetcode
  • python实现动态规划算法的示例代码
    动态规划(Dynamic Programming,DP)是一种常用的算法思想,通常用于解决具有重叠子问题和最优子结构性质的问题。动态规划算法通常是将问题分解为子问题,先解决子问题,再...
    99+
    2023-02-16
    python 动态规划算法
  • 暴力递归转动态规划(二)
    上一篇已经简单的介绍了暴力递归如何转动态规划,如果在暴力递归的过程中发现子过程中有重复解的情况,则证明这个暴力递归可以转化成动态规划。 这篇帖子会继续暴力递归转化动态规划的练习,这道题有点难度。 题目 给定一个整型数组arr[],代表数值不...
    99+
    2023-08-30
    动态规划 算法 java 暴力递归
  • 如何实现动态规划进阶
    本篇内容介绍了“如何实现动态规划进阶”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!案例 1问:给定一个包含非负整数的 m x n 网格,请找...
    99+
    2023-06-15
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作