当前位置: 首页 > news >正文

Kadane算法 C++实现

算法通关之路:一文吃透Kadane算法(C++实现)

在算法面试和日常刷题中,最大子数组和(Maximum Subarray)是一道经典必考题。暴力枚举所有子数组的解法时间复杂度高达 O(n²),而今天要讲的Kadane算法(卡登算法)能以O(n) 时间复杂度 + O(1) 空间复杂度完美解决这个问题,简洁又高效。

今天就用博客的形式,带你从原理到C++代码,彻底掌握Kadane算法!

一、问题背景

先明确问题:给定一个整数数组(包含正数、负数、0),找到一个连续的子数组,使其元素之和最大,返回这个最大和。

示例:

  • 输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
  • 输出:6(对应子数组[4,-1,2,1]

暴力思路:遍历所有起点和终点,计算子数组和取最大值。但数组长度一大就会超时,这时候Kadane算法就派上用场了。

二、Kadane算法核心原理

Kadane算法的核心思想只有一句话:****每一步都做出当前最优选择,最终得到全局最优解(贪心思想)

我们遍历数组时,维护两个关键变量:

  1. 当前最大和(current_max):以当前元素为结尾的连续子数组的最大和。
  2. 全局最大和(global_max):遍历过程中所有子数组的最大和(最终答案)。

核心决策逻辑:
对于数组中的每一个元素nums[i],我们只有两种选择:

  1. nums[i]加入前面的子数组current_max + nums[i]
  2. nums[i]作为新子数组的起点nums[i]

我们取两者的最大值作为新的current_max,保证每一步都是当前最优。
同时,每次更新current_max后,用它更新global_max,记录全局最优。

举个例子理解(数组[-2,1,-3,4]):

  1. 初始:current_max=-2global_max=-2
  2. 元素1:max(1, -2+1)=1 →current_max=1global_max=1
  3. 元素-3:max(-3, 1+(-3))=-2 →current_max=-2global_max=1
  4. 元素4:max(4, -2+4)=4 →current_max=4global_max=4

三、算法步骤(清晰版)

  1. 初始化current_maxglobal_max为数组第一个元素
  2. 从数组第二个元素开始遍历:
    • 更新current_max = max(nums[i], current_max + nums[i])
    • 更新global_max = max(global_max, current_max)
  3. 遍历结束,global_max就是答案。

四、C++ 代码实现

1. 基础版(最简洁,面试首选)

直接实现核心逻辑,无多余操作,时间O(n),空间O(1):

#include<iostream>#include<vector>#include<algorithm>// 用于max函数usingnamespacestd;// Kadane算法:求最大子数组和intmaxSubArray(vector<int>&nums){// 边界判断:数组为空返回0(根据题目要求调整)if(nums.empty())return0;// 初始化当前最大和、全局最大和为第一个元素intcurrent_max=nums[0];intglobal_max=nums[0];// 从第二个元素开始遍历for(inti=1;i<nums.size();++i){// 核心:当前最优选择current_max=max(nums[i],current_max+nums[i]);// 更新全局最优global_max=max(global_max,current_max);}returnglobal_max;}// 测试代码intmain(){vector<int>nums={-2,1,-3,4,-1,2,1,-5,4};cout<<"最大子数组和:"<<maxSubArray(nums)<<endl;// 输出6return0;}

2. 进阶版:记录最大子数组的下标

如果题目不仅要求最大和,还要求输出子数组的起始、结束下标,可以在基础版上稍作修改:

#include<iostream>#include<vector>#include<algorithm>usingnamespacestd;intmaxSubArray(vector<int>&nums,int&start,int&end){if(nums.empty())return0;intcurrent_max=nums[0];intglobal_max=nums[0];inttemp_start=0;// 临时记录当前子数组的起点for(inti=1;i<nums.size();++i){// 选择重新开始:更新临时起点if(nums[i]>current_max+nums[i]){current_max=nums[i];temp_start=i;}else{// 选择加入前面的子数组current_max+=nums[i];}// 更新全局最大和,记录最终起止下标if(current_max>global_max){global_max=current_max;start=temp_start;end=i;}}returnglobal_max;}// 测试代码intmain(){vector<int>nums={-2,1,-3,4,-1,2,1,-5,4};intstart=0,end=0;intmax_sum=maxSubArray(nums,start,end);cout<<"最大子数组和:"<<max_sum<<endl;cout<<"子数组下标:["<<start<<", "<<end<<"]"<<endl;cout<<"子数组:";for(inti=start;i<=end;++i){cout<<nums[i]<<" ";}return0;}

输出结果

最大子数组和:6 子数组下标:[3, 6] 子数组:4 -1 2 1

五、关键细节说明

  1. 全负数数组:Kadane算法依然有效!比如数组[-5,-3,-2,-1],算法会返回最大的单个元素-1(符合题意,因为子数组至少包含一个元素)。
  2. 空间复杂度:基础版只用到两个变量,是最优空间复杂度,无需额外开辟数组。
  3. 适用场景:除了经典的最大子数组和,还能解决最大子矩阵和(二维Kadane)、环形数组最大子数组和等变形题。

六、算法复杂度分析

  • 时间复杂度:O(n) —— 只遍历数组一次,无嵌套循环。
  • 空间复杂度:O(1) —— 仅使用常数个变量,不随数组长度变化。

这也是Kadane算法成为最优解的原因!

七、总结

Kadane算法是贪心思想的经典应用,核心就是每一步只做最优选择

  • 要么延续前面的子数组,要么重新开始新子数组。
  • 时间O(n) + 空间O(1),是最大子数组和问题的最优解法。
  • C++实现简洁,面试手写无压力,还能轻松扩展记录子数组下标。

掌握这个算法,再也不怕最大子数组和相关的面试题啦!


核心要点回顾

  1. 核心思想:贪心,每一步取当前最优(延续/重启子数组)
  2. 关键变量current_max(当前结尾最大和)、global_max(全局最大和)
  3. 复杂度:O(n)时间,O(1)空间
  4. 适用场景:最大子数组和及各类变形题
http://www.cnnetsun.cn/news/2644051.html

相关文章:

  • 别再手动折腾了!用Docker Compose 5分钟搞定Kamailio + MySQL + RTPproxy的SIP服务全家桶
  • Amazon OA 不到二十分钟做完——题目在这里
  • Temu外观侵权投诉!多起侵权链接下架,成功守住产品独家市场!
  • 认知空间曲率与AI幻觉涌现的定量关联模型研究(世毫九实验室原创研究)
  • 【autoresearch 技术解析】Karpathy 开源的自主 ML 实验循环框架深度解析
  • 【Lindy自动化避坑红皮书】:12个生产环境真实故障快照+对应修复代码片段(仅限本周开放下载)
  • AI旅行代理Pack:基于多智能体架构的自主规划与预订系统实践
  • 从2D小地图到3D视角切换:一个Camera组件搞定你的Unity多画面需求(附完整C#脚本)
  • 如何快速解决Windows热键冲突:hotkey-detective热键侦探完全实战指南
  • 一键激活Windows和Office:KMS_VL_ALL_AIO智能激活脚本完全指南
  • 告别手算!用ADS的Filter DesignGuide快速搞定一个4GHz LC低通滤波器
  • WE Learn智能助手终极指南:3步快速上手,学习效率提升300%
  • 抖音批量下载神器:告别手动保存,高效管理你的视频素材库
  • “边骑边充、续航翻倍”是真的吗?
  • ESP8266双源时间同步系统:GPS与NTP自动切换的物联网时钟方案
  • 别再只会点灯了!Keil uVision5的这些高效技巧,能让你的51单片机开发快一倍
  • Jieba、HanLP、LTP... 2024年主流中文分词工具怎么选?一份超全的实战对比指南
  • 5分钟创建专业流程图:Mermaid Live Editor终极指南
  • HW763触摸传感器灵敏度改造:从2mm到15mm的电容感应增强方案
  • 终极Windows风扇控制指南:用FanControl告别电脑噪音与高温烦恼
  • Selenium4相对定位实战:用above、below等新方法,搞定那些XPath和CSS都头疼的动态元素
  • 电解电容的‘寿命焦虑’怎么破?从选型、散热到并联技巧,延长你的电源寿命
  • RF Boy射频开发板:从ESP8266到CC1101的无线信号实验指南
  • 法律AI合规生死线:GDPR/《生成式AI服务管理暂行办法》下Claude使用的5道红线
  • 量子熵流与强耦合效应研究:理论与应用
  • Mac上CORE Keygen打不开?别慌,用Homebrew装个UPX,两步搞定!
  • 全志V3S SPI LCD驱动移植实战:从修改设备树到点亮ST7789屏幕(附避坑指南)
  • FELIX:基于标记-插入两阶段框架的精准文本编辑技术解析
  • AI不会取代人类:从虚构故事协作看技术权力失衡的真正挑战
  • K210的GPIOHS和GPIO有啥区别?MAIX DOCK实战配置详解