【Leetcode】寻找数串中连续最大整数和且最大长度的子串

寻找数串中连续最大整数和且最大长度的子串

输入示例:

1000 -100 200 -200 100 -100 10 90

输出结果:

1100

分析:

分治法解决问题非常方便,依然分为三种情况:a[1], a[2]......a[mid-1], a[mid], a[mid+1]......a[n-1], a[n]

1.最大和数串位于a[mid]左边数串中;

2.最大和数串位于a[mid]右边数串中;

3.最大和数串包括a[mid]。

明显地,情况1,2是原问题的子问题,但情况3则并不是原问题子问题,因为它有条件限制,所以我们需要另外求解。

#include <stdio.h>
#include <stdlib.h>

struct ansmax{
	int lindex;
	int hindex;
	int summax;
};
typedef struct ansmax ans;

int find_cross_max(int *data, int mid, int lindex, int hindex, ans* max){  //计算经过中间点的最大和数串
	int leftmax, rightmax;
	int maxtemp,maxt;
	int k;

	for(k=mid, maxtemp=0, maxt=-100000, leftmax=mid; k>=lindex; k--){  //maxt=负无穷
		maxtemp += *(data+k);
		if(maxtemp>maxt){
			maxt=maxtemp;
			leftmax=k;
		}
	}
	for(k=mid, maxtemp=0, maxt=-100000, rightmax=mid; k<=hindex; k++){
		maxtemp += *(data+k);
		if(maxtemp>maxt){
			maxt=maxtemp;
			rightmax=k;
		}
	}

	//返回经过最大值
	for(k=leftmax, max->summax=0; k<=rightmax; k++){
		max->summax += *(data+k);
		max->lindex = leftmax;
		max->hindex = rightmax;
	}
}

void findmax(int *data, int lindex, int hindex, ans* max){
	ans crossmax;
	ans leftmaxsum, rightmaxsum;
	int mid;

	if(lindex==hindex){
		max->hindex=hindex;
		max->lindex=lindex;
		max->summax=*(data+lindex);
		return;
	}
	mid=(lindex+hindex)/2;
	if(mid-1>=lindex)
		findmax(data, lindex, mid-1, &leftmaxsum);
	else
		leftmaxsum.summax = -100000;  //应该设置为负最大值
	if(mid+1<=hindex)
		findmax(data, mid+1, hindex, &rightmaxsum);
	else
		rightmaxsum.summax = -100000;  //应该设置为负最大值
	find_cross_max(data, mid, lindex,  hindex, &crossmax);
	if(leftmaxsum.summax>rightmaxsum.summax&&leftmaxsum.summax>crossmax.summax){
		max->summax = leftmaxsum.summax;
		max->lindex = leftmaxsum.lindex;
		max->hindex = leftmaxsum.hindex;
	}
	else if(rightmaxsum.summax>leftmaxsum.summax&&rightmaxsum.summax>crossmax.summax){
		max->summax = rightmaxsum.summax;
		max->lindex = rightmaxsum.lindex;
		max->hindex = rightmaxsum.hindex;
	}
	else{
		max->summax = crossmax.summax;
		max->lindex = crossmax.lindex;
		max->hindex = crossmax.hindex;
	}
}

int main(void){
	int datalen;
	int *dataptr;
	int k, sum1, sumtemp1, sum2, sumtemp2;
	int *maxtail, *maxhead, *curptr;
	ans myans;

	printf("input datalen:");  scanf("%d",&datalen);
	if(datalen<=0) return 0;
	if((dataptr=(int*)malloc(sizeof(int)*datalen))==NULL){
		printf("malloc failed
");
		exit(0);
	}
	for(k=0; k<datalen; k++){
		printf("input data %d/%d:", k+1, datalen);
		scanf("%d", dataptr+k);
	}
	
	findmax(dataptr, 0, datalen-1, &myans);
	for(k=myans.lindex; k<=myans.hindex; k++){
		printf("%d ", *(dataptr+k));
	}
	printf("
%d
", myans.summax);

	system("pause");
	return 0;
}

由JULY博客提供的方法,可以大大简化代码的时间复杂度,变为线性复杂度O(n),且空间复杂度为O(1)

其代码为:

#include <stdio.h>
#include <stdlib.h>

int maxsum(int a[],int n)    
{  
    int max=a[0];       //全负情况,返回最大数  
    int sum=0;
	int j;
    for(j=0;j<n;j++)  
    {  
        if(sum>=0)     //如果加上某个元素,sum>=0的话,就加  
            sum+=a[j];  
        else     
            sum=a[j];  //如果加上某个元素,sum<0了,就不加,这里就不清零了  
        if(sum>max)  
            max=sum;  
    }  
    return max;  
}

int main(void){
	int n, k;
	int *a;
	
	scanf("%d", &n);
	a = (int*)malloc(sizeof(int));
	for(k=0; k<n; k++){
		scanf("%d", a+k);
	}

	printf("%d
", maxsum(a,n));

	system("pause");
	return 0;
}




原文地址:https://www.cnblogs.com/xhyzjiji/p/6159393.html