DP动态规划基础题(Kadane算法)

动态规划(Dynamic Programming,简称DP)是一种在数学、管理科学、计算机科学、经济学和生物信息学等领域中使用的,通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。动态规划算法通常用于优化问题,特别是那些具有重叠子问题和最优子结构性质的问题。

动态规划的基本思想
重叠子问题:动态规划算法中,问题被分解成多个子问题,而这些子问题会重复出现多次。如果这些子问题的结果可以被保存下来,那么当它们再次出现时,可以直接使用之前的结果,而不需要重新计算。

最优子结构:一个问题的最优解包含其子问题的最优解。这意味着,如果我们能够找到所有子问题的最优解,那么就能构造出原问题的最优解。

动态规划的步骤
定义状态:确定dp数组(或dp表)中的状态表示什么。通常,状态是问题规模的一个或多个参数。

确定状态转移方程:找出状态之间的关系,即如何从一个或多个较小子问题的解构造出当前问题的解。

确定初始状态和边界条件:确定dp数组的初始值,以及问题的边界条件。

计算顺序:确定如何迭代地填充dp数组,通常从小到大或从上到下。

构造最优解:一旦dp数组被填充,就可以通过它来构造问题的最优解。

动态规划的简单例子
斐波那契数列:计算第n个斐波那契数,其中斐波那契数列定义为:F(0) = 0, F(1) = 1, F(n) = F(n-1) + F(n-2)。

状态:dp[i] 表示第i个斐波那契数。
状态转移方程:dp[i] = dp[i-1] + dp[i-2]。
初始状态和边界条件:dp[0] = 0, dp[1] = 1。
计算顺序:从i = 2到n,依次计算dp[i]。
通过动态规划,我们可以避免重复计算子问题,从而提高算法的效率。动态规划适用于许多问题,如背包问题、最长公共子序列问题、最短路径问题等。
翻转增益的最大子数组和 -
链接: 翻转增益的最大子数组和
题目:
问题描述
给定整数数组,我们称其中连续的 0 个或多个整数为一个子数组,求翻转任一子数组后,新数组中子数组的和的最大值
输入格式
第一行输入为 N,代表数组长度
第二行输入为 N 个整数,依次为数组的每个元素
输出格式
一个整数 K,代表所有可能新数组中子数组的和的最大值
输入样例
5
1 2 3 -1 4
输出样例
10
说明
选择翻转子数组 [-1, 4] 或 [1, 2, 3, -1],新数组分别是 [1, 2, 3, 4, -1] 和 [-1, 3, 2, 1, 4],二者的子数组最大和都是 10
数据范围
50% case:1 <= N <= 100, -100<= arr[i] <= 100
100% case:1 <= N <= 1e6, -100<= arr[i] <= 100
思路:
问题理解
给定一个整数数组,我们可以翻转任意一个子数组(即子数组中的元素顺序颠倒),然后计算新数组中所有子数组的和的最大值。
解题思路

初始子数组和:

首先,计算原始数组中所有子数组的和的最大值。这可以通过Kadane算法来实现。

翻转子数组的影响:

翻转一个子数组会影响该子数组及其周围的子数组的和。我们需要找到一个翻转子数组的方式,使得新数组中子数组的和最大。

计算翻转后的最大子数组和:

对于每个可能的翻转子数组,计算翻转后的新数组中所有子数组的和的最大值。
选择所有可能翻转子数组中,使得新数组中子数组和最大的那个。

关键步骤

Kadane算法:

使用Kadane算法计算原始数组的最大子数组和。

翻转子数组的影响:

对于每个可能的翻转子数组,计算翻转后的新数组中所有子数组的和的最大值。
这可以通过计算翻转子数组的前后部分的最大子数组和来实现。

综合考虑:

综合考虑原始数组的最大子数组和以及所有可能翻转子数组后的最大子数组和,选择最大的那个作为最终答案

Kadane算法是一种用于求解最大子数组和的经典算法。它的核心思想是通过动态规划来逐步计算当前子数组的和,并记录最大子数组的和。
Kadane算法的工作原理

初始化:

初始化两个变量:maxEndingHere 和 maxSoFar。
maxEndingHere 表示以当前元素结尾的最大子数组和。
maxSoFar 表示全局的最大子数组和。

遍历数组:

从数组的第一个元素开始遍历,逐步更新 maxEndingHere 和 maxSoFar。

对于每个元素 array[i],更新 maxEndingHere 为 max(array[i], maxEndingHere + array[i])。

这意味着如果当前元素 array[i] 比 maxEndingHere + array[i] 大,则从当前元素开始重新计算子数组和。

更新 maxSoFar 为 max(maxSoFar, maxEndingHere)。

这意味着记录全局的最大子数组和。

返回结果:

遍历结束后,maxSoFar 即为最大子数组和。

private static int kadane(int[] array) {int maxEndingHere = array[0];int maxSoFar = array[0];for (int i = 1; i < array.length; i++) {maxEndingHere = Math.max(array[i], maxEndingHere + array[i]);maxSoFar = Math.max(maxSoFar, maxEndingHere);}return maxSoFar;
}通过代码:
java 代码解读复制代码public class Main {public static int solution(int N, int[] data_array) {// 计算原始数组的最大子数组和int originalMaxSum = kadane(data_array);// 计算翻转子数组后的最大子数组和int maxSumAfterFlip = originalMaxSum;for (int i = 0; i < N; i++) {for (int j = i; j < N; j++) {// 翻转子数组 [i, j]int[] flippedArray = flipSubarray(data_array, i, j);// 计算翻转后的最大子数组和int flippedMaxSum = kadane(flippedArray);// 更新最大值maxSumAfterFlip = Math.max(maxSumAfterFlip, flippedMaxSum);}}return maxSumAfterFlip;}// Kadane算法计算最大子数组和private static int kadane(int[] array) {int maxEndingHere = array[0];int maxSoFar = array[0];for (int i = 1; i < array.length; i++) {maxEndingHere = Math.max(array[i], maxEndingHere + array[i]);maxSoFar = Math.max(maxSoFar, maxEndingHere);}return maxSoFar;}// 翻转子数组 [start, end]private static int[] flipSubarray(int[] array, int start, int end) {int[] flippedArray = array.clone();while (start < end) {int temp = flippedArray[start];flippedArray[start] = flippedArray[end];flippedArray[end] = temp;start++;end--;}return flippedArray;}public static void main(String[] args) {// 测试用例int N = 4;int[] data_array = {-3, -1, -2, 3};System.out.println(solution(N, data_array)); // 预期输出: 3}
}

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

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

相关文章

计算机组成原理——进位计数制

1.认识不同进制 通常的我们日常生活中用到的都是十进制&#xff0c;比如买东西或者期末成绩等等&#xff0c;当然肯定不止这一种进制方法&#xff0c;相关的还有二进制、八进制、十六进制&#xff0c;还有古罗马数字&#xff0c;通常古罗马数字近似可以看作是五进制的数&#x…

《.addClass()》

《.addClass()》 .addClass() 是一个在网页设计和开发中常用的 jQuery 函数,用于向 HTML 元素添加一个或多个类名。这个函数在美化网页、实现动态效果以及改善用户体验方面发挥着重要作用。本文将详细介绍 .addClass() 函数的用法、优势以及在实际开发中的应用案例。 1. .ad…

function and task

任务和函数 在Verilog语言中提供了任务和函数&#xff0c;可以将较大的行为级设计划分为较小的代码段&#xff0c;允许设计者将需要在多个地方重复使用的相同代码提取出来&#xff0c;编写成任务和函数&#xff0c;这样可以使代码更加简洁和易懂。 1.1任务 任务的定义 任务定义…

【C++】用红黑树封装set和map

在C标准库中&#xff0c;set容器和map容器的底层都是红黑树&#xff0c;它们的各种接口都是基于红黑树来实现的&#xff0c;我们在这篇文章中已经模拟实现了红黑树 ->【C】红黑树&#xff0c;接下来我们在此红黑树的基础上来看看如何封装set和map。 一、共用一颗红黑树 我…

4399 C++面试题及参考答案

C 和 C++ 的区别是什么? C 语言是一种过程式编程语言,而 C++ 是在 C 语言基础上发展而来的面向对象编程语言。 从语法层面来看,C 语言没有类和对象的概念。 而在 C++ 中可以定义类,把数据和操作数据的函数封装在一起,像这样: class Point { public:int x;int y;Point(int…

类与实例

1 问题如何理解类与实例&#xff1f; 2 方法 类与实例 类(class)的概述&#xff1a;用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。 类是一类事物&#xff0c;实例是具体的一个事物。 编程与生活是相通的&#xff0…

kafka常见面试题总结

Kafka 核心知识解析 一、Kafka 消息发送流程 Kafka 发送消息涉及两个线程&#xff1a;main 线程和 sender 线程。在 main 线程中&#xff0c;会创建一个双端队列 RecordAccumulator&#xff0c;main 线程负责将消息发送给 RecordAccumulator&#xff0c;而 sender 线程则从 R…

Rust 所有权机制

Rust 所有权机制 本文示例代码地址 所有权是Rust中最独特的特性&#xff0c;它让Rust无需GC就可以保证内存安全。 什么是所有权&#xff1f; 所有权&#xff08;ownership&#xff09;是 Rust 用于如何管理内存的一组规则。所有程序都必须管理其运行时使用计算机内存的方式…

2024/11/4 计网强化

10: 17: 22: 09: 11: 12: 13&#xff1a; 14&#xff1a; 15&#xff1a; 18&#xff1a; 19&#xff1a; 20: 21: 16:

hutool-雪花算法 id 生成器

配置 workId 和 datacenterId 设置工作机器ID&#xff08;workerId&#xff09;和数据中心ID&#xff08;datacenterId&#xff09;&#xff0c;这两个参数用于确保在分布式环境中生成的ID是唯一的。使用配置 yaml 文件的方式获取&#xff0c;配置方式参考&#xff1a;https:/…

CentOS 9 配置网卡

在 CentOS 9 中配置网卡&#xff0c;通常涉及以下几个步骤&#xff1a; 1. 查看网络接口 首先&#xff0c;确认系统上存在的网络接口。可以使用 ip 命令或 ifconfig 命令查看网络接口的状态。 ip a 或者&#xff1a; ifconfig 这将列出所有可用的网络接口&#xff08;例如…

力扣104 : 二叉树最大深度

补&#xff1a;二叉树的最大深度 描述&#xff1a; 给定一个二叉树 root &#xff0c;返回其最大深度。二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 何解&#xff1f; 树一般常用递归&#xff1a;递到叶子节点开始倒着处理

机器情绪及抑郁症算法

&#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f916;编程探索专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2024年11月12日17点02分 点击开启你的论文编程之旅https://www.aspiringcode.com/content?id17230869054974 计算机来理解你的情绪&a…

M4 lotus 源码编译安装

查看系统版本 sw_vers ProductName: macOS ProductVersion: 15.1安装依赖 xcode-select -p /Library/Developer/CommandLineToolsbrew install go jq pkg-config hwloc coreutilscurl --proto https --tlsv1.2 -sSf https://sh.rustup.rs | sh设置环境变量 export LIBRARY…

JAVA学习日记(十五) 数据结构

一、数据结构概述 数据结构是计算机底层存储、组织数据的方式。 数据结构是指数据相互之间以什么方式排列在一起的。 数据结构是为了更加方便的管理和使用数据&#xff0c;需要结合具体的业务场景来进行选择。 二、常见的数据结构 &#xff08;一&#xff09;栈 特点&…

i春秋-SQLi(无逗号sql注入,-- -注释)

练习平台地址 竞赛中心 题目描述 后台有获取flag的线索应该是让我们检查源码找到后台 题目内容 空白一片 F12检查源码 发现login.php 访问login.php?id1 F12没有提示尝试sql注入 常规sql注入 //联合注入得到表格列数 1 order by 3 # 1 union select 1,2,3 #&#xff08…

sql注入之二次注入(sqlilabs-less24)

二阶注入&#xff08;Second-Order Injection&#xff09;是一种特殊的 SQL 注入攻击&#xff0c;通常发生在用户输入的数据首先被存储在数据库中&#xff0c;然后在后续的操作中被使用时&#xff0c;触发了注入漏洞。与传统的 SQL 注入&#xff08;直接注入&#xff09;不同&a…

nginx 部署2个相同的vue

起因&#xff1a; 最近遇到一个问题&#xff0c;在前端用nginx 部署 vue&#xff0c; 发现如果前端有改动&#xff0c;如果不适用热更新&#xff0c;而是直接复制项目过去&#xff0c;会404 因此想到用nginx 负载两套相同vue项目&#xff0c;然后一个个复制vue项目就可以了。…

MySQL:CRUD

MySQL表的增删改查&#xff08;操作的是表中的记录&#xff09; CRUD(增删改查) C-Create新增R-Retrieve检查&#xff0c;查询U-Update更新D-Delete删除 新增&#xff08;Create&#xff09; 语法&#xff1a; 单行数据全列插入 insert into 表名[字段一&#xff0c;字段…

centos7 node升级到node18

使用jenkins发布vue3项目提示node18安装失败 错误日志&#xff1a; /var/lib/jenkins/tools/jenkins.plugins.nodejs.tools.NodeJSInstallation/Node18/bin/node: /lib64/libm.so.6: version GLIBC_2.27 not found (required by /var/lib/jenkins/tools/jenkins.plugins.node…