最大子序列和的四种求解算法及其时间比较
1、T(N)=O(N^3)
__int64 algorithm1(__int64 a[],__int64 n) //T(N)=O(N^3)
{__int64 MaxSum = 0;__int64 ThisSum;for(__int64 i = 0; i < n; i++) //i从零开始到最后一个数字{for(__int64 j = i; j < n; j++) //j从i开始到最后一个数字{ThisSum = 0;//PS:第一轮循环k从0->0,0->1,0->2...0->n//PS:第二轮循环k从1->1,1->2,1->3...1->n//PS:第K轮循环k从k->k,k->k+1,k->k+2...k->n//PS:这样就遍历完序列中所有子序列的可能性for(__int64 k = i; k <= j; k++) //从i开始到j的数字相加ThisSum += a[k];if(ThisSum > MaxSum) //大于最大子序列之和则替换MaxSum = ThisSum;}}return MaxSum;
}
2、T(N)=O(N^2)
__int64 algorithm2(__int64 a[],__int64 n) //T(N)=O(N^2)
{__int64 MaxSum = 0;__int64 ThisSum;for(__int64 i = 0; i < n; i++) //i从零开始到最后一个数字{ThisSum = 0;//PS:第一轮j从0->n,每循环一次,判断一次//PS:第二轮j从1->n,每循环一次,判断一次//PS:第J轮j从j->n,每循环一次,判断一次//PS:这样就遍历完序列中所有子序列的可能性for(__int64 j = i; j < n; j++) //j从i开始到最后一个数字{ThisSum += a[j];if(ThisSum > MaxSum) //大于最大子序列之和则替换MaxSum = ThisSum;}}return MaxSum;
}
3、T(N)=O(NlogN),底数为2
PS:用分治法,先将原序列分成相似的两个子序列,这样可以得出一个结论,
那就是最大子序列和要不在左子序列中,要不在右子序列中,要不在左子序列和右子序列的连接处
对左子序列递归求最大序列和,对右子序列求最大序列和,再将左右子序列连接起来,求连接处的最大序列和
最后比较就能求出整体最大序列和
__int64 MaxSubSum(__int64 a[],__int64 Left,__int64 Right)
{__int64 Center; //中间元素__int64 MaxLeftSum,MaxRightSum; //左右子序列最大序列和__int64 MaxLeftBorderSum,MaxRightBorderSum; //左右边界最大序列和__int64 LeftBorderSum,RightBorderSum; //左右边界序列和if(Left == Right) //递归出口if(a[Left] > 0) //当a[i]>0时,返回该元素return a[Left];else //否则返回0return 0;Center = (Left + Right) / 2;MaxLeftSum = MaxSubSum(a,Left,Center); //递归求解左子序列MaxRightSum = MaxSubSum(a,Center + 1,Right); //递归求解右子序列MaxLeftBorderSum = 0;LeftBorderSum = 0;for(__int64 i = Center; i>= Left; i--) //求左边界最大序列和{LeftBorderSum += a[i];if(LeftBorderSum > MaxLeftBorderSum)MaxLeftBorderSum = LeftBorderSum;}MaxRightBorderSum = 0;RightBorderSum = 0;for(__int64 i = Center + 1; i <= Right; i++) //求右边界最大序列和{RightBorderSum += a[i];if(RightBorderSum > MaxRightBorderSum)MaxRightBorderSum = RightBorderSum;}return max(max(MaxLeftSum,MaxRightSum),MaxLeftBorderSum+MaxRightBorderSum); //返回整体最大序列和
}__int64 algorithm3(__int64 a[],__int64 n) //T(N)=O(NlogN),底数为2
{return MaxSubSum(a,0,n - 1);
}
4、T(N)=O(N)
推荐用这种算法
__int64 algorithm4(__int64 a[],__int64 n) //T(N)=O(N)
{__int64 ThisSum = 0;__int64 MaxSum = 0;for(int i = 0; i < n; i++) //i从零开始到最后一个数字{ThisSum += a[i];if(ThisSum < 0) //当a[j]+...+a[i] < 0,则舍弃i之前的所有序列,从i后继续累加ThisSum = 0;if(ThisSum > MaxSum) //求出当前序列的最大子序列和MaxSum = ThisSum;}return MaxSum;
}
5、数量级及其时间比较表格
Algorithm | 1 | 2 | 3 | 4 | |||||
Time | O(N^3) | T/N Rate | O(N^2) | T/N Rate | O(NlogN) | T/N Rate | O(N) | T/N Rate | |
Input Size(N) | 10 | 0.903 | 0.0903 | 0.771 | 0.0771 | 0.734 | 0.0734 | 0.707 | 0.0707 |
100 | 1.069 | 0.01069 | 0.791 | 0.00791 | 0.784 | 0.00784 | 0.744 | 0.00744 | |
1000 | 3.538 | 0.003538 | 0.952 | 0.000952 | 0.805 | 0.000805 | 0.78 | 0.00078 | |
10000 | 3000 | 0.3 | 1.599 | 0.0001599 | 1.067 | 0.0001067 | 0.859 | 0.0000859 | |
100000 | 3000000 | 30 | 73.844 | 0.00073844 | 1.255 | 0.00001255 | 1.125 | 0.00001125 |
6、源代码及其测试数据
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <ctime>
using namespace std;__int64 algorithm1(__int64 a[],__int64 n) //T(N)=O(N^3)
{__int64 MaxSum = 0;__int64 ThisSum;for(__int64 i = 0; i < n; i++) //i从零开始到最后一个数字{for(__int64 j = i; j < n; j++) //j从i开始到最后一个数字{ThisSum = 0;//PS:第一轮循环k从0->0,0->1,0->2...0->n//PS:第二轮循环k从1->1,1->2,1->3...1->n//PS:第K轮循环k从k->k,k->k+1,k->k+2...k->n//PS:这样就遍历完序列中所有子序列的可能性for(__int64 k = i; k <= j; k++) //从i开始到j的数字相加ThisSum += a[k];if(ThisSum > MaxSum) //大于最大子序列之和则替换MaxSum = ThisSum;}}return MaxSum;
}__int64 algorithm2(__int64 a[],__int64 n) //T(N)=O(N^2)
{__int64 MaxSum = 0;__int64 ThisSum;for(__int64 i = 0; i < n; i++) //i从零开始到最后一个数字{ThisSum = 0;//PS:第一轮j从0->n,每循环一次,判断一次//PS:第二轮j从1->n,每循环一次,判断一次//PS:第J轮j从j->n,每循环一次,判断一次//PS:这样就遍历完序列中所有子序列的可能性for(__int64 j = i; j < n; j++) //j从i开始到最后一个数字{ThisSum += a[j];if(ThisSum > MaxSum) //大于最大子序列之和则替换MaxSum = ThisSum;}}return MaxSum;
}//PS:用分治法,先将原序列分成相似的两个子序列,这样可以得出一个结论,
//那就是最大子序列和要不在左子序列中,要不在右子序列中,要不在左子序列和右子序列的连接处
//对左子序列递归求最大序列和,对右子序列求最大序列和,再将左右子序列连接起来,求连接处的最大序列和
//最后比较就能求出整体最大序列和
__int64 MaxSubSum(__int64 a[],__int64 Left,__int64 Right)
{__int64 Center; //中间元素__int64 MaxLeftSum,MaxRightSum; //左右子序列最大序列和__int64 MaxLeftBorderSum,MaxRightBorderSum; //左右边界最大序列和__int64 LeftBorderSum,RightBorderSum; //左右边界序列和if(Left == Right) //递归出口if(a[Left] > 0) //当a[i]>0时,返回该元素return a[Left];else //否则返回0return 0;Center = (Left + Right) / 2;MaxLeftSum = MaxSubSum(a,Left,Center); //递归求解左子序列MaxRightSum = MaxSubSum(a,Center + 1,Right); //递归求解右子序列MaxLeftBorderSum = 0;LeftBorderSum = 0;for(__int64 i = Center; i>= Left; i--) //求左边界最大序列和{LeftBorderSum += a[i];if(LeftBorderSum > MaxLeftBorderSum)MaxLeftBorderSum = LeftBorderSum;}MaxRightBorderSum = 0;RightBorderSum = 0;for(__int64 i = Center + 1; i <= Right; i++) //求右边界最大序列和{RightBorderSum += a[i];if(RightBorderSum > MaxRightBorderSum)MaxRightBorderSum = RightBorderSum;}return max(max(MaxLeftSum,MaxRightSum),MaxLeftBorderSum+MaxRightBorderSum); //返回整体最大序列和
}__int64 algorithm3(__int64 a[],__int64 n) //T(N)=O(NlogN),底数为2
{return MaxSubSum(a,0,n - 1);
}__int64 algorithm4(__int64 a[],__int64 n) //T(N)=O(N)
{__int64 ThisSum = 0;__int64 MaxSum = 0;for(int i = 0; i < n; i++) //i从零开始到最后一个数字{ThisSum += a[i];if(ThisSum < 0) //当a[j]+...+a[i] < 0,则舍弃i之前的所有序列,从i后继续累加ThisSum = 0;if(ThisSum > MaxSum) //求出当前序列的最大子序列和MaxSum = ThisSum;}return MaxSum;
}__int64 Random(__int64 m,__int64 n) //指定范围内随机数
{__int64 pos,dis;if(m == n) //m=n则表示范围内只有一个数字{return m;}else if(m > n) //m>n则说明取[m,n]区间内数字{pos = n;dis = m - n + 1;return rand() % dis + pos;}else //m>n则说明取[n,m]区间内数字{pos = m;dis = n - m + 1;return rand() % dis + pos;}
}void MakeRandomSequences(__int64 m,__int64 n,__int64 num) //产生随机序列
{ofstream filerandom("G:\\sequences.txt");srand((int)time(NULL)); //根据时间产生相应种子值for(int i=0 ; i < num; i++){filerandom << Random(m,n) <<" ";if(!((i + 1) % 10)) //数据量逢十换行filerandom << endl;}filerandom.close();
}
int main()
{
//测试数据
// __int64 a[] = {4,-3,5,-2,-1,2,6,-2};
// __int64 n = 8;
// cout << algorithm1(a,n) << endl;
// cout << algorithm2(a,n) << endl;
// cout << algorithm3(a,n) << endl;
// cout << algorithm4(a,n) << endl;// MakeRandomSequences(-1000,1000,100000); //产生随机序列__int64 a[200000];__int64 n = 0;ifstream filesequ("G:\\sequences.txt");if(!filesequ.is_open()) //打开失败处理{cout<<"Error opening file";return -1;}while(!filesequ.eof()){filesequ >> a[n++];}filesequ.close();//PS:测试只需要把调用算法注释去掉
// cout << algorithm1(a,n) << endl;
// cout << algorithm2(a,n) << endl;
// cout << algorithm3(a,n) << endl;cout << algorithm4(a,n) << endl;return 0;
}
最大子序列和的四种求解算法及其时间比较相关推荐
- php主要算法设计,四种排序算法设计(PHP)
标签 详细分析 /** * 四种排序算法设计(PHP) * * 1) 插入排序(Insertion Sort)的基本思想是: 每次将一个待排序的记录,按其关键字大小插入到前面已经排好序的子文件中的适当 ...
- JVM之垃圾收集机制四种GC算法详解
JVM之四种GC算法详解 目录: 什么是GC? GC算法之引用计数法 GC算法之复制算法(Copying) GC算法之标记清除(Mark-Sweep) GC算法之标记压缩(Mark-Compact) ...
- php四种基础算法:冒泡,选择,插入和快速排序法
许多人都说 算法是程序的核心,一个程序的好于差,关键是这个程序算法的优劣.作为一个初级phper,虽然很少接触到算法方面的东西 .但是对于冒泡排序,插入排序,选择排序,快速排序四种基本算法,我想还是要 ...
- 【JVM】四种GC算法(分代收集+三种标记算法)
目录 参考文章 四种GC算法 分代收集算法(理论) 标记清除算法 标记整理算法 标记复制算法 三种算法的优缺点 参考文章 JVM的4种垃圾回收算法.垃圾回收机制与总结_我是guyue,guyue就是我 ...
- java向MySQL插入当前时间的四种方式和java时间日期格式化的几种方法(案例说明)...
转载地址:http://www.devba.com/index.php/archives/4581.html java向MySQL插入当前时间的四种方式和java时间日期格式化的几种方法(案例说明); ...
- 关于几种排序算法的时间性能比较
以前经常看到各种排序算法,今天也对以下6种排序算法的时间性能做了一次测试: 测试代码地址 1. 冒泡排序 O(n^2) /** 冒泡排序 @Param {[]int} arr 整形切片 */ func ...
- mysql java 日期格式化_(转)java向MySQL插入当前时间的四种方式和java时间日期格式化的几种方法(案例说明)...
java向MySQL插入当前时间的四种方式和java时间日期格式化的几种方法(案例说明);部分资料参考网络资源 1. java向MySQL插入当前时间的四种方式 第一种:将java.util.Date ...
- java实现子序列最大和_算法入门:最大子序列和的四种算法(Java)
最近再学习算法和数据结构,推荐一本书:Data structures and Algorithm analysis in Java 3rd 以下的四种算法出自本书 四种最大子序列和的算法: 问题描述 ...
- 求最大子序列和的四种方法
求一个给定序列的连续子序列中和最大的那个子序列的和,下边方法只求和,没有找出最大子序列. 用到的头文件和宏定义如下 #include "stdafx.h" #include< ...
最新文章
- HashSet 和 TreeSet的区别
- mpvue微信小程序动画_mpvue微信小程序系列
- 使用snmp4j实现Snmp功能(三)
- C# 不支持关键字: “.;database”。
- 深度 | 理解深度学习中的卷积
- 创建型模式、结构型模式和行为型模式_设计模式之创建型模式
- Android学习之Activity
- 【原创】brew 和 brew cask
- RabbitMQ学习——常见概念详解
- 浅谈Vue 中的 computed 和 methods 的使用
- Python入门篇-基础数据类型整型(int),字符串(str)和切片(slice)
- Android游戏SQL注入,关于Android contentprovider sql注入问题
- linux 列出指定目录下所有文件的 列表集合
- Photoshop - 新建纯色图层
- 应用,传输层协议和端口对应关系
- Win10添加Loopback网卡
- 【ROS2原理11】C++编程的要点
- TexStudio编写Latex碰到的问题
- HTML5 Web Audio Api-2 发声oscillator
- Docker安装Elasticsearch及安装中文分词插件
热门文章
- Linux下Apache安装与配置(详细步骤+代码+验证)
- Tomcat本地正常!但是部署到服务器后,mysql插入中文乱码问题解决!
- linux常用指令 查看端口占用情况
- 【Linux 命令】云服务器 ECS (CentOS) 开启防火墙操作
- 大数据 Hive spark Flink 关系
- [极客大挑战 2019]PHP
- C#LeetCode刷题-拒绝采样
- struts2中Action名称的搜索顺序
- 找软件开发开发工作_将求职变成开发项目
- g2是一种编程语言吗_我写了一种编程语言。 这也是您可以的方式。