首页 > 试题广场 >

给出一个数列(元素个数不多于100),数列元素均为负整数、0

[问答题]
最大连续子数列和
给出一个数列(元素个数不多于100),数列元素均为负整数、0、正整数。请找出数列中的一个连续子数列,使得这个子数列中包含的所有元素之和最大,在和最大的前提下还要求该子数列包含的元素个数最多,并输出这个最大和以及该连续子数列在整个数列中的位置。
例如数列为4  -5  3  2  4时,输出“和为9,子数列起始位置为2,结束位置为4”;再比如数列为1  2  3  -5  0  7  8时,输出“和为16,子数列起始位置为0,结束位置为6”。
键盘输入:为两行,第一行为数列元素个数,第二列依次输入各个元素。
7
1 2 3 -5 0 7 8
屏幕输出:
和为16,子数列起始位置为0,结束位置为6
#include<stdio.h>
int seek(int a[100],int n,int *p1,int *p2)
{
	int i1,i2,i3,t1=0,t2=n-1,sum=0,max;
	for (i1=0;i1<n;i1++)
	{
		for (i2=n-1;i2>=i1;i2--)
		{
			for (i3=0;i3<=i2;i3++)
			    sum=sum+a[i3];
			if (i1==0&&i2==n-1)
				max=sum;
			else 
			{
				if (sum>max)
				{
					t1=i1;
					t2=i2;
					max=sum;
				}
				else if (sum==max)
				{
					if (i2-i1>t2-t1)
					{
						t1=i1;
						t2=i2;
					}
				}
			}
			sum=0;
		}
	}
	*p1=t1;
	*p2=t2;
	return (max);
}
void main()
{
	int a[100],t1,t2,n,i,max;
	int *p1,*p2;
	scanf("%d",&n);
	fflush(stdin);
	for (i=0;i<n;i++)
		scanf("%d",&a[i]);
	p1=&t1;
	p2=&t2;
    max=seek(a,n,p1,p2);
	printf("和为%d,子数列起始位置为%d,结束位置为%d\n",max,t1,t2);
}


O(n)
int max_sub_sum(int a[]; unsigned int n) {
int this_sum=0,max_sum=0,best_i=-1,best_j=-1;
for(int i =0,j=0; j < n; j++){
this_sum += a[j];
if(this_sum > max_sum) {
max_sum = this_sum;
best_i = i;
best_j = j;
} else if(this_sum == max_sum && best_j - best_i < j - i) {
best_i=i;
best_j=j;
}
if(this_sum < 0) {
i = j + 1;
this_sum = 0;
}
}
return max_sum;
}

编辑于 2017-09-22 20:22:32 回复(0)
#include <iostream>
using namespace std;
int main()
{
 int n,sum=0,k,mus=0;
 cin>>n;
 int a[n];
 for(int i=0;i<=n-1;i++)
 {
  cin>>a[i];
 }
 for(int u=0;u<=n;u++)
 {
  for(int j=u;j<=n-1;j++)
  { 
   sum=0;
   for(int k=u;k<=j;k++)
   {
    sum=sum+a[k];
    if(sum>mus) mus=sum;
   }
  }
 }
 cout<<mus<<endl;
 for(int u=0;u<=n;u++)
 {
  for(int j=u;j<=n-1;j++)
  { 
   sum=0;
   for(k=u;k<=j;k++)
   {
    sum=sum+a[k];
   }
  if(sum==mus)
  {
   for(k=u;k<=j;k++) cout<<a[k]<<" ";
   cout<<'\n';
  }
  }
 }
 
}
发表于 2018-11-12 21:38:09 回复(0)
#include<stdio.h>
int main()
{
    char c;
    int a[1000];
    int s,e;
    int max=0,sum=0;
    int i,n;
    scanf("%d",&n);
    for(i=0;i<n;i++)
    {
        scanf("%d",&a[i]);
    }
    s=0;
    e=n;
    for(i=0;i<n;i++)
    {
        sum += a[i];
        if(sum <= 0)
        {
            s=i;
            e=n;
        }
        else
        {
            if(max < sum)
            {
                e=i;
                max = sum;
            }
        }
    }
    for(i=s;i<=e;i++)
    {
        printf("%d ",a[i]);
    } 
    printf("\n%d %d %d",s,e,max);
}


//一个整体思想
//如果从s到e序列的和为0,则把该段看作0, s跳到下一个数,e回到n
// 如果sum不为0,表示从s到n在看做一个整体的时候,与下一个数据a[i]相加后依然有增益 ,则把e后移到 i
//当在不为0的sum中间找到最大的sum,即是最大子段和,最大公共子序列即是从s到e为下标的数组。 

发表于 2018-04-02 11:11:13 回复(0)