【数据结构与算法】Kadane‘s算法(动态规划、最大子数组和)

2023-11-21 00:04

本文主要是介绍【数据结构与算法】Kadane‘s算法(动态规划、最大子数组和),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 一、算法原理
  • 二、例题
    • 2.1 最大子数组和
    • 2.2 环形子数组的最大和

一、算法原理

Kadane's算法是一种用于解决最大子数组和问题的动态规划算法。这类问题的目标是在给定整数数组中找到一个连续的子数组,使其元素之和最大(数组含有负数)。

算法的核心思想是通过迭代数组的每个元素,维护两个变量来跟踪局部最优解和全局最优解。

以下是Kadane’s算法的详细步骤:

  1. 初始化:

    • 令 maxEndingHere 表示在当前位置结束的最大子数组和,初始值为数组的第一个元素。
    • 令 maxSoFar 表示全局最大子数组和,初始值也为数组的第一个元素。
  2. 迭代:

    • 从数组的第二个元素开始迭代。

    • 对于每个元素,计算在当前位置结束的最大子数组和:
      maxEndingHere = max(nums[i], maxEndingHere + nums[i]);
      这表示要么继续当前子数组,要么从当前位置开始一个新的子数组。

    • 更新全局最大子数组和:
      maxSoFar = max(maxSoFar, maxEndingHere);
      如果在当前位置结束的子数组和大于全局最大和,更新全局最大和。

  3. 返回结果:

    • 当迭代完成后,maxSoFar 中存储的即为最大子数组和。

复杂度:

  • 时间复杂度:O(n),其中 n 为 nums 数组的长度。我们只需要遍历一遍数组即可求得答案。
  • 空间复杂度:O(1)。我们只需要常数空间存放若干变量。

图例:
在这里插入图片描述

简要说明:(如过当前值比前面的局部最大值+当前值还大,那么就从当前值开始继续计算局部最大值)

  1. i=0,maxEndingHere 、maxSoFar 初始值都为数组第一个元素,-2;
  2. 开始循环,i=1,maxEndingHere = max(nums[1], maxEndingHere + nums[1]),即maxEndingHere = max(1, -2 + 1)=1,maxSoFar=1;
  3. i=2, maxEndingHere = max(nums[2], maxEndingHere + nums[2]),即maxEndingHere = max(-3, 1 - 3)=-2,maxSoFar=1;
  4. i=3,maxEndingHere = max(nums[3], maxEndingHere + nums[3]),即maxEndingHere = max(4, -2 + 4)=4,maxSoFar=4;

二、例题

2.1 最大子数组和

在这里插入图片描述

解答:

int maxSubArray(int* nums, int numsSize) {int maxEndingHere  = nums[0], maxSoFar = nums[0];for (int i = 1; i < numsSize; i++) {maxEndingHere  = fmax(maxEndingHere  + nums[i], nums[i]);maxSoFar = fmax(maxSoFar, maxEndingHere );}return maxSoFar;
}

fmax是<math.h>中的函数,用于比较2个数字的大小,双精度。

简单换个写法:

int maxSubArray(int* nums, int numsSize) {int maxEndingHere  = nums[0], maxSoFar = nums[0];for (int i = 1; i < numsSize; i++) {maxEndingHere  = maxEndingHere  + nums[i]>nums[i]?maxEndingHere  + nums[i]:nums[i];maxSoFar = maxSoFar>maxEndingHere?maxSoFar:maxEndingHere;}return maxSoFar;
}

简单用三目表达式代替fmax函数。

2.2 环形子数组的最大和

在这里插入图片描述

解答:

int maxSubarraySumCircular(int* nums, int numsSize) {if (nums == NULL || numsSize == 0) return 0;int maxSum = nums[0], minSum = nums[0];int maxCur = nums[0], minCur = nums[0];int sum = nums[0];for (int i = 1; i < numsSize; i++) {sum += nums[i];maxCur = fmax(nums[i], maxCur + nums[i]);minCur = fmin(nums[i], minCur + nums[i]);maxSum = fmax(maxSum, maxCur);minSum = fmin(minSum, minCur);}if (maxSum < 0) return maxSum; // 如果所有数都是负数,返回最大值return fmax(maxSum, sum - minSum); // 返回“不跨越头尾的最大子数组和”和“跨越头尾的最大子数组和”中的较大者
}

这篇关于【数据结构与算法】Kadane‘s算法(动态规划、最大子数组和)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/398401

相关文章

Java 字符数组转字符串的常用方法

《Java字符数组转字符串的常用方法》文章总结了在Java中将字符数组转换为字符串的几种常用方法,包括使用String构造函数、String.valueOf()方法、StringBuilder以及A... 目录1. 使用String构造函数1.1 基本转换方法1.2 注意事项2. 使用String.valu

Python中的随机森林算法与实战

《Python中的随机森林算法与实战》本文详细介绍了随机森林算法,包括其原理、实现步骤、分类和回归案例,并讨论了其优点和缺点,通过面向对象编程实现了一个简单的随机森林模型,并应用于鸢尾花分类和波士顿房... 目录1、随机森林算法概述2、随机森林的原理3、实现步骤4、分类案例:使用随机森林预测鸢尾花品种4.1

VUE动态绑定class类的三种常用方式及适用场景详解

《VUE动态绑定class类的三种常用方式及适用场景详解》文章介绍了在实际开发中动态绑定class的三种常见情况及其解决方案,包括根据不同的返回值渲染不同的class样式、给模块添加基础样式以及根据设... 目录前言1.动态选择class样式(对象添加:情景一)2.动态添加一个class样式(字符串添加:情

SpringCloud配置动态更新原理解析

《SpringCloud配置动态更新原理解析》在微服务架构的浩瀚星海中,服务配置的动态更新如同魔法一般,能够让应用在不重启的情况下,实时响应配置的变更,SpringCloud作为微服务架构中的佼佼者,... 目录一、SpringBoot、Cloud配置的读取二、SpringCloud配置动态刷新三、更新@R

JAVA中整型数组、字符串数组、整型数和字符串 的创建与转换的方法

《JAVA中整型数组、字符串数组、整型数和字符串的创建与转换的方法》本文介绍了Java中字符串、字符数组和整型数组的创建方法,以及它们之间的转换方法,还详细讲解了字符串中的一些常用方法,如index... 目录一、字符串、字符数组和整型数组的创建1、字符串的创建方法1.1 通过引用字符数组来创建字符串1.2

如何提高Redis服务器的最大打开文件数限制

《如何提高Redis服务器的最大打开文件数限制》文章讨论了如何提高Redis服务器的最大打开文件数限制,以支持高并发服务,本文给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录如何提高Redis服务器的最大打开文件数限制问题诊断解决步骤1. 修改系统级别的限制2. 为Redis进程特别设置限制

如何用Python绘制简易动态圣诞树

《如何用Python绘制简易动态圣诞树》这篇文章主要给大家介绍了关于如何用Python绘制简易动态圣诞树,文中讲解了如何通过编写代码来实现特定的效果,包括代码的编写技巧和效果的展示,需要的朋友可以参考... 目录代码:效果:总结 代码:import randomimport timefrom math

vue如何监听对象或者数组某个属性的变化详解

《vue如何监听对象或者数组某个属性的变化详解》这篇文章主要给大家介绍了关于vue如何监听对象或者数组某个属性的变化,在Vue.js中可以通过watch监听属性变化并动态修改其他属性的值,watch通... 目录前言用watch监听深度监听使用计算属性watch和计算属性的区别在vue 3中使用watchE

Java中JSON字符串反序列化(动态泛型)

《Java中JSON字符串反序列化(动态泛型)》文章讨论了在定时任务中使用反射调用目标对象时处理动态参数的问题,通过将方法参数存储为JSON字符串并进行反序列化,可以实现动态调用,然而,这种方式容易导... 需求:定时任务扫描,反射调用目标对象,但是,方法的传参不是固定的。方案一:将方法参数存成jsON字

.NET利用C#字节流动态操作Excel文件

《.NET利用C#字节流动态操作Excel文件》在.NET开发中,通过字节流动态操作Excel文件提供了一种高效且灵活的方式处理数据,本文将演示如何在.NET平台使用C#通过字节流创建,读取,编辑及保... 目录用C#创建并保存Excel工作簿为字节流用C#通过字节流直接读取Excel文件数据用C#通过字节