Python 动态规划(DP)套路总结

Python 动态规划(DP)套路总结

在解决算法问题时,动态规划(DP) 是一种非常常见的优化技巧,它可以通过保存子问题的结果来避免重复计算,从而减少时间复杂度。Python 提供了非常方便的语法特性,使得实现动态规划变得相对简单。下面是一些常见的 Python 语法DP 解题套路

1. Python 语法和技巧

1.1 列表初始化

在 Python 中,动态规划通常需要一个数组来存储子问题的解,常见的初始化方法有:

  • 一维数组

    dp = [0] * n  # 初始化一个长度为 n 的数组,元素均为 0
    
  • 二维数组

    dp = [[0] * m for _ in range(n)]  # 初始化一个 n x m 的二维数组,元素均为 0
    
  • 处理边界情况
    如果问题涉及到无效值(例如负无穷),可以初始化为非常小的数字:

    dp = [-float('inf')] * n  # 初始化为负无穷
    

1.2 枚举排列

  • 枚举排列:通常用于动态规划中,确定所有的选择路径:

    for i in range(n):for j in range(i, n):  # 遍历子数组# 在这里进行状态转移
    
  • 利用索引生成排序后的顺序

    sorted_idx = sorted(range(len(arr)), key=lambda i: arr[i])  # 排序并记录原始索引
    

2. 动态规划(DP)解题套路

2.1 状态定义

首先,需要定义一个或多个状态,表示每个子问题的结果。常见的状态定义如下:

  • dp[i] 表示前 i 个元素的最大和或最小值
  • dp[i][j] 表示在第 i 个位置选择了 j 种操作后的最优解
  • 对于某些题目,可能需要额外记录其他信息,如最大或最小值、索引等。

2.2 状态转移方程

根据题目要求,写出从一个状态转移到另一个状态的递推公式。一般来说,转移方程会根据前一个状态的结果来更新当前状态。

2.3 边界条件

动态规划通常从小的子问题开始,需要明确边界条件:

  • dp[0] 可能是初始化的最小值。
  • dp[1] 可能是初始值或第一个元素的特殊处理。

2.4 最终解的选择

在动态规划的过程中,我们最终希望找到全局最优解(例如最大值或最小值)。通常,我们需要通过 max(dp)min(dp) 来获取结果。


3. 题目解析与动态规划解法

题目:1186. 删除一次得到子数组最大和

题目描述

给定一个整数数组 arr,返回它的某个非空子数组(连续元素)在执行一次可选的删除操作后,所能得到的最大元素总和。换句话说,你可以从原数组中选出一个子数组,并可以决定要不要从中删除一个元素(只能删一次哦),删除后该子数组中至少应当有一个元素。

示例
arr = [1,-2,0,3]
输出: 4

解释:

  • 我们可以选择子数组 [1, -2, 0, 3],删除 -2,得到 [1, 0, 3],最大和为 4
解法思路

对于这个问题,我们可以使用 动态规划(DP) 来处理。考虑两种情况:

  1. 不删除任何元素 的情况下,子数组的最大和。
  2. 删除一个元素后,子数组的最大和。

1. 定义状态

  • dp[i][0]:表示到第 i 个元素为止,不删除任何元素时的最大和。
  • dp[i][1]:表示到第 i 个元素为止,删除一个元素后的最大和。

2. 状态转移方程

  • dp[i][0]:可以选择加入当前元素,或者从当前元素开始一个新的子数组:
    dp[i][0] = max(arr[i], dp[i-1][0] + arr[i])
    
  • dp[i][1]:可以选择删除当前元素,或者删除前一个元素并加上当前元素:
    dp[i][1] = max(dp[i-1][0], dp[i-1][1] + arr[i])
    

3. 边界条件

  • dp[0][0] = arr[0],表示子数组只有第一个元素的情况。
  • dp[0][1] = -inf,表示第一个元素不能删除,因为至少要保留一个元素。

4. 最终解

我们需要考虑两种情况的最大值:

  • dp[i][0] 表示不删除元素的最大和。
  • dp[i][1] 表示删除一个元素后的最大和。

最终的解是 max(max(dp[i][0] for i in range(n)), max(dp[i][1] for i in range(n)))
在这里插入图片描述

代码实现
class Solution:def maximumSum(self, arr: List[int]) -> int:n = len(arr)# 初始化 dp 数组,初始值为负无穷dp = [[-2e9, -2e9] for _ in range(n)]# 初始化第一个元素的情况dp[0][0] = arr[0]dp[0][1] = float('-inf')  # 删除第一个元素不合法# 动态规划遍历for i in range(1, n):dp[i][0] = max(arr[i], dp[i - 1][0] + arr[i])  # 不删除dp[i][1] = max(dp[i - 1][0], dp[i - 1][1] + arr[i])  # 删除一个元素# 返回最大结果return max(max(dp[i][0] for i in range(n)), max(dp[i][1] for i in range(n)))
解析:
  1. 初始化:我们初始化了 dp 数组,并为第一个元素设定了边界条件。
  2. 状态转移:我们通过遍历 arr 数组,逐步计算 dp[i][0]dp[i][1],表示不删除元素和删除元素后的最大和。
  3. 返回结果:最后返回 dp 数组中最大的值,即为子数组的最大和。

时间复杂度与空间复杂度:

  • 时间复杂度O(n),我们只遍历了一次数组,并进行常数时间的计算。
  • 空间复杂度O(n),需要一个大小为 n 的动态规划数组。

总结

动态规划(DP)是解决子问题最优解的强大工具。在此题中,我们利用了动态规划的状态定义转移方程来解决删除一次元素后的子数组最大和问题。在处理此类问题时,理解状态定义与转移方程至关重要,它能够帮助我们高效地得出最终的最优解。
两种状态 没有行使权力的最大数组和 行使权力后的最大数组和
没有行使权力可以另起炉灶一个新的或者继承之前的
行使权力的可以继承之前的,或者行使权力不删集成没有行使权力的

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/71830.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ESP32驱动OV3660摄像头实现yoloV5物体分类(摄像头支持红外夜视、边缘AI计算)

目录 1、传感器特性 2、硬件原理图 3、驱动程序 ESP32-S3 AI智能摄像头模块是一款专为智能家居和物联网应用打造的高性能边缘AI开发模组。它集成了摄像头、麦克风、音频功放、环境光传感器和夜视补光灯,无需依赖云端即可实现本地化AI推理。 凭借TensorFlow Lite、YOLO和O…

RReadWriteLock读写锁应用场景

背景 操作涉及一批数据,如订单,可能存在多个场景下操作,先使用读锁,从redis缓存中获取操作中数据 比如 关闭账单, 发起调账, 线下结算, 合并支付 先判断当前操作的数据,是否在…

网络安全高级软件编程技术 网络安全 软件开发

安全软件开发入门 软件安全问题 有趣的《黑客帝国》终极解释: 《黑客帝国》故事里面的人物关系,就像电脑里面的各种程序的关系一样: 电脑里面的系统程序:Matrix; 病毒程序:以Neo为首的人类; 防病…

苹果商店上架流程,app上架发布流程

苹果商店地址 https://appstoreconnect.apple.com/login 其他地址:开发 - Apple Developer 1.更新代码 将项目的代码更新到最新,更新成功后右下角会给出提示 2.打开模拟器 鼠标右键可以选择设备(Device) 3.测试运行 如下图可以看到已经识别到设备了,点击运行即可,运行到模…

正点原子[第三期]Arm(iMX6U)Linux移植学习笔记-2.1 uboot简介

前言: 本文是根据哔哩哔哩网站上“Arm(iMX6U)Linux系统移植和根文件系统构键篇”视频的学习笔记,在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。 引用: …

Better-SQLite3 参数绑定详解

Better-SQLite3 参数绑定详解 在使用 better-sqlite3 进行数据库操作时,参数绑定是一个非常重要的概念。它不仅提高了代码的可读性和安全性,还能有效防止 SQL 注入攻击。本文将详细介绍如何在 better-sqlite3 中使用匿名参数和命名参数,并展…

C++编程:进阶阶段—4.1封装

C面向对象的三大特性:封装、继承、多态 具有相同性质的对象,抽象为类 4.1 封装 封装的意义:将属性和行为作为一个整体,表现生活中的事物,并将属性和行为加以权限控制。 4.1.1 类的定义及实例化对象 语法&#xff…

运行OpenManus项目(使用Conda)

部署本项目需要具备一定的基础:Linux基础、需要安装好Anaconda/Miniforge(Python可以不装好,直接新建虚拟环境的时候装好即可),如果不装Anaconda或者Miniforge,只装过Python,需要确保Python是3.…

spring boot + vue 搭建环境

参考文档:https://blog.csdn.net/weixin_44215249/article/details/117376417?fromshareblogdetail&sharetypeblogdetail&sharerId117376417&sharereferPC&sharesourceqxpapt&sharefromfrom_link. spring boot vue 搭建环境 一、浏览器二、jd…

MPPT与PWM充电原理及区别详解

MPPT(最大功率点跟踪)和PWM(脉宽调制)是太阳能充电控制器中常用的两种技术,它们在原理、效率和适用场景上有显著区别。以下是两者的详细对比: 1. 工作原理 PWM(脉宽调制) 核心机制…

slam学习笔记9---ubuntu2004部署interactive_slam踩坑记录

背景:interactive_slam是一款可用于离线优化点云地图算法。部署安装容易出问题,这里记录一下。 一、安装基本流程 绝大部分跟着readme走,g2o安装使用apt安装 interactive_slam depends on the following libraries:GL3W GLFW Dear ImGui p…

视觉图像处理

在MATLAB中进行视觉图像处理仿真通常涉及图像增强、滤波、分割、特征提取等操作。以下是一个分步指南和示例代码,帮助您快速入门: 1. MATLAB图像处理基础步骤 1.1 读取和显示图像 % 读取图像(替换为实际文件路径) img = imread(lena.jpg); % 显示原图 figure; subplot(2…

用java如何利用jieba进行分词

在Java中使用jieba进行分词,可以借助jieba的Java版本——jieba-analysis。jieba-analysis是一个基于jieba分词算法的Java实现,支持精确模式、全模式和搜索引擎模式等多种分词方式。 以下是使用jieba-analysis进行分词的详细步骤和示例代码: …

【含文档+PPT+源码】Python爬虫人口老龄化大数据分析平台的设计与实现

项目介绍 本课程演示的是一款Python爬虫人口老龄化大数据分析平台的设计与实现,主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的 Python学习者。 1.包含:项目源码、项目文档、数据库脚本、软件工具等所有资料 2.带你从零开始部署运行本…

【A2DP】SBC 编解码器互操作性要求详解

目录 一、SBC编解码器互操作性概述 二、编解码器特定信息元素(Codec Specific Information Elements) 2.1 采样频率(Sampling Frequency) 2.2 声道模式(Channel Mode) 2.3 块长度(Block Length) 2.4 子带数量(Subbands) 2.5 分配方法(Allocation Method) 2…

Android双亲委派

下面是一份 Android 类加载器双亲委派机制的时序图示例,描述了当应用调用 loadClass() 时,各个加载器之间的委派过程。 #mermaid-svg-rBdlhpD2uRjBPiG8 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mer…

记录小白使用 Cursor 开发第一个微信小程序(二):创建项目、编译、预览、发布(250308)

文章目录 记录小白使用 Cursor 开发第一个微信小程序(二):创建项目、编译、预览、发布(250308)一、创建项目1.1 生成提示词1.2 生成代码 二、编译预览2.1 导入项目2.2 编译预览 三、发布3.1 在微信开发者工具进行上传3…

Linux系统管理二

目录 一.远程连接管理服务SSH 1.1 了解服务端和客户端 1.2 了解端口号的设定 1.3 了解ssh服务的作用 1.4 ssh搭建服务 二.netstat 2.1 netstat简介 2.2 netstat命令参数 2.3 常用命令参考 三.进程的检测与控制 3.1 管道 3.1.1 什么是管道 3.1.2 管道的分类 3.1.3…

【Recon】Git源代码泄露题目解题方法

CTF中Git源代码泄露题目解题方法 1. 确认存在.git目录泄露2. 下载完整的.git目录3. 恢复Git仓库历史4. 查找Flag的常见位置5. 处理不完整的.git目录6. 其他技巧示例流程 在CTF中遇到Git源代码泄露题目时,通常可以通过以下步骤解决: 1. 确认存在.git目录泄…

字符串 反转函数reverse() 的错误用法

回文字符串 题目描述 如果一个字符串逆序后与正序相同,那么称这个字符串为回文字符串。例如abcba是回文字符串,abcca不是回文字符串。 给定一个字符串,判断它是否是回文字符串。 输入描述 一个非空字符串(长度不超过 50&#…