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

news2024/11/14 6:17:31

动态规划(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.coloradmin.cn/o/2239979.html

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

相关文章

Web安全之SQL注入---基础

文章目录 SQL注入简介SQL注入基础SQL注入分类SQL注入流程 SQL注入简介 什么是SQL注入&#xff1f; SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严&#xff0c;攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句&#xff0c;在管理…

iOS 18.1,未公开的新功能

童锦程祖师爷曾说过&#xff1a;“发誓可以&#xff0c;发朋友圈不行。”表面上看是渣男语录&#xff0c;实际上也说明了人们对隐私的看重。 在当今生活中&#xff0c;智能手机可能是最私密的电子产品&#xff0c;没有之一。不管是照片、联系人、短信、APP数据&#xff0c;甚至…

网页版五子棋——对战模块(服务器端开发②)

前一篇文章&#xff1a;网页版五子棋——对战模块&#xff08;服务器端开发①&#xff09;-CSDN博客 项目源代码&#xff1a;Java: 利用Java解题与实现部分功能及小项目的代码集合 - Gitee.com 目录 前言 一、创建并注册 GameAPI 类 1.创建 GameAPI 类 2.注册 GameAPI 类 …

★ C++进阶篇 ★ 异常

Ciallo&#xff5e;(∠・ω< )⌒☆ ~ 今天&#xff0c;我将和大家一起学习C中的异常 ~ ​❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️ 澄岚主页&#xff1a;椎名澄嵐-CSDN博客 C基础篇专栏&#xff1a;★ C基础篇 ★_椎名澄嵐的博客-CSDN博客 C进阶篇专栏&am…

MFC图形函数学习08——绘图函数的重载介绍

在《MFC图形函数学习06——画椭圆弧线函数》中介绍了CPoint类、POINT结构体&#xff1b;在《MFC图形函数学习07——画扇形函数》中介绍了CRect类、RECT结构体。在介绍完后&#xff0c;没有介绍它们怎样使用。实际上&#xff0c;这些类和结构体对象或指针也是我们学习过的绘图函…

尽量通俗易懂地概述.Net U nity跨语言/跨平台相关知识

本文参考来自唐老狮,Unity3D高级编程:主程手记,ai等途径 仅作学习笔记交流分享 目录 1. .Net是什么? 2. .Net框架的核心要点? 跨语言和跨平台 .Net x Unity跨平台发展史 Net Framework 2002 Unity跨平台之 Mono 2004 Unity跨平台之 IL2CPP 2015 二者区别 .NET Core …

Flink执行sql时报错

[ERROR] Could not execute SQL statement. Reason: java.lang.ClassNotFoundException: org.apache.flink.table.planner.delegation.ParserFactory flink-1.15.4的lib里面存在flink-sql-connector-hive-3.1.2_2.12-1.15.4.jar时&#xff0c;似乎会跟hdfs产生冲突&#xff0c…

实现API接口的自动化

API接口自动化测试的最佳实践有哪些&#xff1f; API接口自动化测试的最佳实践包括以下几个方面&#xff1a; 确定测试范围和目标&#xff1a;明确需要测试的API接口和功能点&#xff0c;确定测试的目标和预期结果 编写测试用例&#xff1a;根据API文档和需求&#xff0c;编…

uni-app中使用 unicloud 云开发平台③

文章目录 六、hbuilderX 中使用 unicloud 云开发平台文档传统业务开发流程什么是 unicloudunicloud 优点开发流程uncloud 构成云数据库云存储及 CDN创建云函数工程七、unicloud api 操作云函数调用云函数实现云数据库基本增删改查1. 获取数据库引用云存储操作六、hbuilderX 中使…

【缓存策略】你知道 Refresh-ahead(预刷新)这个缓存策略吗?

👉博主介绍: 博主从事应用安全和大数据领域,有8年研发经验,5年面试官经验,Java技术专家,WEB架构师,阿里云专家博主,华为云云享专家,51CTO 专家博主 ⛪️ 个人社区:个人社区 💞 个人主页:个人主页 🙉 专栏地址: ✅ Java 中级 🙉八股文专题:剑指大厂,手撕 J…

零基础Java第十六期:抽象类接口(二)

目录 一、接口&#xff08;补&#xff09; 1.1. 数组对象排序 1.2. 克隆接口 1.3. 浅拷贝和深拷贝 1.4. 抽象类和接口的区别 一、接口&#xff08;补&#xff09; 1.1. 数组对象排序 我们在讲一维数组的时候&#xff0c;使用到冒泡排序来对数组里的元素进行从小到大或从大…

django入门【05】模型介绍(二)——字段选项

文章目录 1、null 和 blank示例说明⭐ null 和 blank 结合使用的几种情况总结&#xff1a; 2、choices**choices 在 Django 中有以下几种形式&#xff1a;**&#xff08;1&#xff09; **简单的列表或元组形式**&#xff08;2&#xff09; **字典映射形式**&#xff08;3&#…

数据量大Excel卡顿严重?选对报表工具提高10倍效率

当几万行的数据把软件频频跑崩&#xff0c;当珍贵的数据资源无法便捷复用&#xff0c;当数据填报的本地文档在各个电脑中传来传去……在各大岗位要求中频频出现的Excel&#xff0c;作为个人办公软件绝无仅有&#xff0c;但作为企业场景下的报表工具&#xff0c;效率显然不足。 …

如何用WordPress和Shopify提升SEO表现?

选择合适的建站程序对于SEO优化非常重要。目前&#xff0c;WordPress和Shopify是两种备受推崇的建站平台&#xff0c;各有优势。 WordPress最大的优点是灵活性。它支持大量SEO插件&#xff0c;帮助你调整元标签、生成站点地图、优化内容结构等。这些功能让你能够轻松地提升网站…

vue 计算属性get set

<template><div id"app"><h1>用户信息</h1><p>全名&#xff1a;{{ fullName }}</p><input v-model"fullName" placeholder"请输入全名" /><p>姓&#xff1a;{{ firstName }}</p><p>…

PHP搭建开发环境(Windows系统)

要搭建一个完整的PHP动态网站&#xff0c;离不开操作系统、Web服务器、数据库、和PHP软件。 虽然有不错方便的方式&#xff0c;比如使用phpstudio等等等等许多面板都是非常快速不错的方式&#xff0c;但是这里是教会大家如何配置而不只是依赖别人整合好的面板软件&#xff0c;…

7.2 图像复原之空间滤波

图像复原&#xff08;只存在噪声的复原&#xff09;之空间滤波 文章目录 图像复原&#xff08;只存在噪声的复原&#xff09;之空间滤波前言1. 均值滤波器1.1 算术平均滤波器1.2 几何均值滤波器1.3 谐波平均滤波器1.4 反谐波平均滤波器 总结 前言 当一幅图像仅被加性噪声退化时…

化工防爆巡检机器人:在挑战中成长,为化工安全保驾护航

随着全球能源需求的不断攀升&#xff0c;化工行业的安全性与高效性愈发受到关注。化工设施规模巨大&#xff0c;而且其中多数存在高风险因素&#xff0c;像是易燃易爆化学物质、高温环境、有毒有害物质以及高压设备等。仅2023年&#xff0c;国内危化品事故就多达652起&#xff…

【数字图像处理+MATLAB】对图片进行伽马校正(Gamma Correction):使用幂律变换公式进行伽马变换

引言 伽马校正&#xff08;Gamma Correction&#xff09;是一种用于图像处理的技术&#xff0c;主要用于调整图像的亮度或对比度。其基本原理是对图像的每一个像素应用一个非线性变换&#xff0c;以更好地适应人眼的视觉感知。在数字图像处理中&#xff0c;伽马校正通常用于调…

scala 迭代更新

在Scala中&#xff0c;迭代器&#xff08;Iterator&#xff09;是一种用于遍历集合&#xff08;如数组、列表、集合等&#xff09;的元素而不暴露其底层表示的对象。迭代器提供了一种统一的方法来访问集合中的元素&#xff0c;而无需关心集合的具体实现。 在Scala中&#xff0c…