zoukankan      html  css  js  c++  java
  • 数据结构(一)-----4种方法求最大子列和

    数据结构(一)-----4种方法求最大子列和

    1、暴力算法

    /*
    作者:mys
    功能:求最大子列和
    日期:2018/7/23
    */
    #include<stdio.h>
    #include<stdlib.h>
    #define N 1000
    int maxSubseSum(int a[], int n);
    void main()
    {
    	int a[N] = { 0 },i;
    	for (i = 0; i < N; i++)
    		a[i] = rand() % 10000;
    	printf("maxSubseSum=%d
    ", maxSubseSum(a, N));
    	system("pause");
    }
    
    int maxSubseSum(int a[],int n)
    {
    	int thisSum, maxSum = 0;
    	int i, j, k;
    	for (i = 0; i < n; i++)//i是子列左端位置
    	{
    		for (j = i; j < n; j++)//j是子列右端位置
    		{
    			thisSum = 0;//thisSum:a[i]到a[j]的子列和
    			for (k = i; k <= j; k++)
    			{
    				thisSum += a[k];
    				if (thisSum>maxSum)//更新结果
    					maxSum = thisSum;
    			}
    		}
    	}
    	return maxSum;
    }
    
    

    因为有3重for循环,因此时间复杂度为:T(N)=O(N^3),时间复杂度太大,不理想,下面是稍微优化后的。

    2、稍微优化

    #include<stdio.h>
    #include<stdlib.h>
    #define N 1000
    int maxSubseSum(int a[], int n);
    void main()
    {
    	int a[N] = { 0 }, i;
    	for (i = 0; i < N; i++)
    		a[i] = rand() % 10000;
    	printf("maxSubseSum=%d
    ", maxSubseSum(a, N));
    	system("pause");
    }
    
    int maxSubseSum(int a[], int n)
    {
    	int thisSum, maxSum = 0;
    	int i, j;
    	for (i = 0; i < n; i++)//i是子列左端位置
    	{
    		thisSum = 0;//thisSum:a[i]到a[j]的子列和
    		for (j = i; j < n; j++)//j是子列右端位置
    		{
    				thisSum += a[j];
    				if (thisSum>maxSum)//更新结果
    					maxSum = thisSum;
    
    		}
    	}
    	return maxSum;
    }
    
    

    T(N)=O(N^2)
    时间复杂度稍微好一点,但还是比较大,程序员一般看到时间复杂度是N^2,就会想办法将其复杂度变为NlogN,因此出现了下面的分而治之法。

    3、分而治之

    /*
    作者:mys
    功能:求最大子列和(分而治之)
    */
    #include<stdio.h>
    #include<stdlib.h>
    #define N 1000
    
    //求三个数的最大值
    int Max(int a, int b, int c)
    {
    	int max;
    	max = (a > b) ? a : b;
    	max = (max > c) ? max : c;
    	return max;
    }
    
    //遍历整个子列求最大值
    int maxCross(int a[], int left, int mid, int right)
    {
    	int leftSum=0,rightSum=0,sum=0;
    	int i;
    	//遍历从中间到左边
    	for (i = mid; i >=left; i--)
    	{
    		sum += a[i];
    		if (sum > leftSum)
    			leftSum = sum;
    	}
    	//遍历从中间到右边
    	sum = 0;
    	for (i = mid + 1; i <= right; i++)
    	{
    		sum += a[i];
    		if (sum > rightSum)
    			rightSum = sum;
    	}
    	return leftSum + rightSum;
    }
    
    //分而治之
    int divideAndRule(int a[], int left,int right)
    {
    	int mid=0;
    	int maxLeft=0, maxRight=0, maxMiddle=0;
    	//如果只有一个数
    	if (left == right)
    	{
    		if (a[left] > 0)
    			return a[left];
    		else 
    			return 0;
    	}
    	//求中间值
    	mid = (left + right) / 2;
    	//对左边的子列用分而治之法
    	maxLeft = divideAndRule(a, left, mid);
    	//对右边的子列用分而治之法
    	maxRight = divideAndRule(a, mid + 1, right);
    	//遍历整个子列
    	maxMiddle = maxCross(a,left,mid,right);
    	return Max(maxLeft, maxRight, maxMiddle);
    }
    
    void main()
    {
    	int a[N] = { 0 }, i;
    	for (i = 0; i < N; i++)
    		a[i] = rand() % 10000;
    	printf("divideAndRule=%d
    ", divideAndRule(a, 0, N - 1));
    	system("pause");
    }
    

    此程序的时间复杂度计算如下:
    这里写图片描述
    T(N)为程序的整个递归的时间复杂度,因此前半的时间复杂度为T(N/2);不断替换,直到T(1);其中N/2^k=1是因为N不断除2,约为k次,因此k=logN 注:复杂度分析小窍门
    这个时间复杂度为NlogN,还算比较优化,但还不是最优的方法,下面这个在线处理方法算是最优化的,时间复杂度T(N)=O(N),就算遍历完整个子列也需要O(N),因此这个算法是最优化的了。

    4、在线处理

    /*
    作者:mys
    功能:求最大子列和(在线处理)
    */
    #include<stdio.h>
    #include<stdlib.h>
    #define N 1000
    
    void main()
    {
    	int a[N] = { 0 }, i;
    	for (i = 0; i < N; i++)
    		a[i] = rand() % 10000;
    	printf("onlineProcess=%d
    ", onlineProcess(a,N));
    	system("pause");
    }
    
    int onlineProcess(int a[], int n)
    {
    	int sum = 0, maxSum = 0;
    	int i;
    	for (i = 0; i < n; i++)
    	{
    		sum += a[i];//向右累加
    		if (sum>maxSum)
    			maxSum = sum;//更新结果
    		else if (sum < 0)//如果当前子列和为负,则不可能使后面部分的值增大,因此舍去
    			maxSum = 0;
    	}
    	return maxSum;
    }
    

    下图是这四个算法的运行时间比较

    这里写图片描述
    NA表示not avaliable,从上可看出分而治之O(NlogN)在线处理O(N) 算法还是比较好。

    ----------------------------------------------------------------------------------2018.7.23以上是我今天整理的数据结构的一点小小的笔记,以后还会继续更新-

  • 相关阅读:
    默认值设置
    关于设置 存储 内部存储空间只显示图片不显示视频的解决方法
    sd卡的监听
    android 设置时间12/24小时制
    详解BMP木马
    C#中类和接口的设计思想(本人认为比较好的思想,欢迎大家讨论指点)
    从XML中读取数据到内存的实例
    如何在代码中通过命令行创建SQL SERVER 数据库
    Visual Studio 2005 新特性 之 可空类型
    install shield11.5 如何制作卸载程序
  • 原文地址:https://www.cnblogs.com/xq-mys/p/9353643.html
Copyright © 2011-2022 走看看