《算法导论》——MaximumSubArray
今天我们讨论的算法是最大子数组问题。
首先我定义了一个类用来保存最大子数组的开始位置索引、结束位置索引和该数组的和。代码如下:

class MaximumSubArray { private: int begin; //开始位置索引 int end; //结束位置索引 int sum; //和 public: void setBegin(int Begin) { begin=Begin; } void setEnd(int End) { end=End; } void setSum(int Sum) { sum=Sum; } int getBegin() { return begin; } int getEnd() { return end; } int getSum() { return sum; } };
该算法采用分治策略,我们先讨论最大子数组跨越中点位置的情况:

MaximumSubArray FindMaxCrossingSubArray(int *numArray,int low,int middle,int high) { MaximumSubArray max; int leftsum=numArray[middle]; int maxleft=middle; int sum=0; for(int i=middle;i>=low;i--) { sum+=numArray[i]; if(sum>=leftsum) { leftsum=sum; maxleft=i; } } int rightsum=numArray[middle+1]; int maxright=middle+1; sum=0; for(int j=middle+1;j<=high;j++) { sum+=numArray[j]; if(sum>=rightsum) { rightsum=sum; maxright=j; } } max.setBegin(maxleft); max.setEnd(maxright); max.setSum(leftsum+rightsum); return max; }
接下来是二分法求最大子数组:

MaximumSubArray FindMaximumSubArray(int *numArray,const int low,const int high) { MaximumSubArray max; if(high==low) { max.setBegin(low); max.setEnd(high); max.setSum(numArray[low]); return max; } if(high-1==low) { max.setBegin(high); max.setEnd(high); max.setSum(numArray[high]); return max; } int middle=(low+high)/2; MaximumSubArray left=FindMaximumSubArray(numArray,low,middle); MaximumSubArray right=FindMaximumSubArray(numArray,middle,high); MaximumSubArray cross=FindMaxCrossingSubArray(numArray,low,middle,high); if(left.getSum()>=right.getSum()&&left.getSum()>=cross.getSum()) max=left; else if(right.getSum()>left.getSum()&&right.getSum()>=cross.getSum()) max=right; else max=cross; return max; }
注意:
该书中的伪代码并没有以下这段
if(high-1==low) { max.setBegin(high); max.setEnd(high); max.setSum(numArray[high]); return max; }
因为在算法递归到数组中只有两个元素的时候,算出的middle值和low值是一样的(& 索引为0和1的两个元素),所以,在high==low的时候去索引小的元素,在high-1=low的时候取索引大的元素,避免无限循环。
以上代码,请放到如下注释的位置,保存为SubArray.h
#include <stdlib.h> namespace dksl { // // // }
下面是程序测试代码及运行结果:

#include "stdafx.h" #include <iostream> #include "SubArray.h" using namespace std; using namespace dksl; int _tmain(int argc, _TCHAR* argv[]) { int a[16] = {13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7}; MaximumSubArray max=FindMaximumSubArray(a,0,15); cout<<"begin:"<<max.getBegin()<<endl; cout<<"end:"<<max.getEnd()<<endl; cout<<"sum:"<<max.getSum()<<endl; system("PAUSE"); return 0; }
该算法的时间复杂度为θ(nlogn)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端