最大子列和问题的四种不同时间复杂度的算法实现
来源:互联网 发布:为什么淘宝搜不到店铺 编辑:程序博客网 时间:2024/05/16 23:48
最近在学习计算机专业课,数据结构课程。在中国大学MOOC网上选修了浙大的《数据结构》课程。最近课程讲到了最大子序列和的问题,结合课程内容、网上的资料借鉴和自己的理解,将解决这个问题的四种不同的算法进行实现和总结。整个工程的代码已经上传。
问题描述:
主函数代码如下:
#include<iostream>#include<time.h>using namespace std;#define NUM_SUM 10int A[NUM_SUM] = {1, 1, 5, -4, 21, -6, 3, 7, -12, 7};int MaxSubseqSum1(int A[], int N);int MaxSubseqSum2(int A[], int N);int MaxSubseqSum3(int A[], int N);int MaxSubseqSum4(int A[], int N);int GetBorderSubseqSum(int A[], int left, int right);int main(){int maxNum = 0;cout <<"系统每秒打点数" << CLK_TCK << endl;clock_t tStart,tStop;tStart = clock();//起始时间//算法执行1000次for(int i=0;i<1000;i++)for(int i=0;i<10000;i++)maxNum = MaxSubseqSum1(A, NUM_SUM);tStop = clock();//结束时间cout << "算法执行时间:" << ((tStop - tStart)/CLK_TCK*1.0/1000) << endl;cout << "结果:" << maxNum << endl;cin.get();cin.get();return 0;}算法一:暴力求解,时间复杂度:N*N*N。代码实现如下:
//暴力求解//时间复杂度为: N*N*Nint MaxSubseqSum1(int A[], int N){int thisNum=0, maxSum=0;//左边起始端for(int i=0;i<N;i++){//右边起始端for(int j=i;j<N;j++){thisNum =0;//索引到中间的每个数据for(int k=i;k<=j;k++)thisNum +=A[k];if(thisNum>maxSum)maxSum = thisNum;}}return maxSum;}复杂度浪费在第三个for循环。
算法二:时间复杂度:N*N*。代码实现如下:
//复杂度为N*N的算法int MaxSubseqSum2(int A[], int N){int thisNum=0, maxSum=0;//左边起始端for(int i=0;i<N;i++){thisNum = 0;//左边起始端每变化一次,将thisNum置0一次//右边起始端for(int j=i;j<N;j++){thisNum+=A[j];if(thisNum>maxSum)maxSum = thisNum;}}return maxSum;}思想:左边的起始端每变化一次将thisNum置0一次,左边起始端定了,在左边起始端到最右边分别有N-i个不同的子列,但是这些子列起始端都是i的位置,每次左边起始端定了,在后面的N-i个子列中求取和最大的那个值,然后在改变左边的起始端。
算法三:分而治之算法,时间复杂度N*logN。代码实现如下:
/分为治之的思想//时间复杂度为N*logNint MaxSubseqSum4(int A[], int N){//获取左右边界int left = 0, right = N-1;//只有一个元素if(left == right){if(A[left]<0)return 0;elsereturn A[left];}return GetBorderSubseqSum(A, left, right);}//将一个小的子列块求其最大列和//该函数是一个递归调用的函数int GetBorderSubseqSum(int A[], int left, int right){//只有一个元素if(left == right){if(A[left]<0)return 0;elsereturn A[left];}//获取边界int mid = (left+right)/2;int nBorderMaxSum = 0;//左右最大列和值//获取左右两快中最大和数int nMaxLeftNum = GetBorderSubseqSum(A, left, mid);int nMaxRightNum = GetBorderSubseqSum(A, mid+1, right);//考虑中间这一一种情况//1向左检索int nTempMaxLeftSum =0;//左边检索的最大和值int nLeftSum=0;for(int i=mid;i>=left;i--){nLeftSum +=A[i];if(nLeftSum>nTempMaxLeftSum)nTempMaxLeftSum=nLeftSum;}//2、向右检索int nTempMaxRightSum =0;//右边检索的最大和值int nRightSum=0;for(int i=mid+1;i<=right;i++){nRightSum +=A[i];if(nRightSum>nTempMaxRightSum)nTempMaxRightSum=nRightSum;}nBorderMaxSum = nTempMaxLeftSum+nTempMaxRightSum;//对nBorderMaxSum、nMaxLeftNum、nMaxRightNum三者取最大的if(nMaxLeftNum>=nMaxRightNum){if(nMaxLeftNum>=nBorderMaxSum)return nMaxLeftNum;elsereturn nBorderMaxSum;}else{if(nMaxRightNum>=nBorderMaxSum)return nMaxRightNum;elsereturn nBorderMaxSum;}}分而治之的思想:就是将一个列分成左右两个部分,左右子列,分别求左右两个子列的最大和数,再求跨越两个子列的最大列和数,最后求三者中的最大值就是 所要求的的最大列和数。注意:这个算法是利用递归的思想,考虑算法的空间复杂度,如果输入的数据量太大,可能造成算法无法运行出正确结果。
关于这个思想的理解,以下截图来自课程中视频:
算法四:在线处理处理算法,时间复杂度:N。代码实现如下:
//在线处理算法,时间复杂度为Nint MaxSubseqSum3(int A[], int N){int thisNum=0, maxSum=0;for(int i=0;i<N;i++){thisNum+=A[i];if(thisNum>maxSum)maxSum = thisNum;//如果当前和小于0,则将其丢弃置0,因为其对后面没有作用,只能使后面的更小else if(thisNum<0)thisNum =0;}return maxSum;}在线的意思是每次输入一个数据就进行即时处理,在任何地方终止输入算法,都能给出正确结果。
0 0
- 最大子列和问题的四种不同时间复杂度的算法实现
- 求最大连续子列和的算法和时间复杂度的分析(包含四种不同时间复杂度的算法)
- 最大子序列和的四种不同复杂度实现
- 最大子序列和的四种不同复杂度实现
- 最大子列和问题的不同实现算法
- 求解最大子列和问题的四种算法
- 数组连续子序列的最大的和-四种算法,四种时间复杂度
- 数组连续子序列的最大的和;四种算法,四种时间复杂度
- 求最大子序列和的四种经典方法及其算法时间复杂度分析
- 最大子序列的不同时间复杂度算法
- 最大子序列的3种不同时间复杂度的算法
- 求最大子列和的四种算法
- 最大子列和的四种算法比较
- 最大子数组 三种不同复杂度的算法
- 时间复杂度_最大子列和问题
- C++解决最大子列和问题,算法时间复杂度优化
- 不同时间复杂度实现最大子段和
- 最大子段和算法 不同复杂度方法实现
- [cs229] k-means 图像压缩
- java操作redis3.0集群
- adnroid.appwidget.AppWidgetProvider
- mongoDB——自动分片介绍及简单实现
- Android:finished with non-zero exit value
- 最大子列和问题的四种不同时间复杂度的算法实现
- opencv两张同大小图片合并重叠
- OpenStack启动虚拟机时Nova内部工作流程
- 用tar进行Centos系统备份与恢复教程
- mysql水平拆分与垂直拆分的详细介绍
- Ubuntu上TensorFlow配置教程
- Morris.js(前端)
- char* 转 LPCWSTR 解决方案
- 常用的正则表达式大全(转摘)