最大子列和问题

问题如下:


使用在线处理的方法,“在线”的意思是指每输入一个数据就进行即时处理,在任何一个地方中止输入,算法都能正确给出当前的解。

算法每次向右累加一次,就进行处理,如果当前的子列和小于0,则再继续向右加也不会是最大值,所以将其抛弃,从下一个数当做果起点从新开始累加。如果当前子列和大于过去的最大子列和,更新之。


代码如下:

#include <stdio.h>
#include <malloc.h>

int main() {
  
  int  K = 0;
  scanf("%d",&K);   //输入K
  int * arr = (int *)malloc(sizeof(int)*(K+1)); 
  int i;
  for(i=0; i<K; ++i) {
    scanf("%d",arr+i);   //输入数组
  }
  
  printf("%d",MaxSubseqSum(K,arr));
  
  return 0;
}

int MaxSubseqSum(int K, int * arr) {
  
  int MaxSum = 0;    //最大子列和
  int ThisSum = 0;   //当前子列和
  int i;
  for(i=0; i<K; ++i) {
    ThisSum += arr[i];   //向右累加
    if(ThisSum < 0) {    //如果当前子列和小于0,抛弃
      ThisSum = 0;   
    }
    if(ThisSum > MaxSum) {  //更新最大值
      MaxSum = ThisSum;
    }
  }
  
  return MaxSum;
}
 

如果将问题增加为还要输出该子列的第一个和最后一个元素:


要返回该子列的开始和结束元素,首要要定位开始和结束的位置。返回结束位置还是比较容易的,我们知道,每当更新最大和时,便对应可能的结束下标,这个时候,只要将结束位置记录下来即可。当确定最大值后再往回累加便可找到开始位置。

#include <stdio.h>
#include <malloc.h>

int MaxSubseqSum(int K, int * arr, int *FirstNum, int *LastNum);

int main() {
  
  int  K = 0;
  scanf("%d",&K);   //输入K
  int * arr = (int *)malloc(sizeof(int)*(K+1)); 
  int i;
  for(i=0; i<K; ++i) {
    scanf("%d",arr+i);   //输入数组
  }
  int MaxSum,FirstNum,LastNum;
  
  MaxSum = MaxSubseqSum(K,arr,&FirstNum,&LastNum);
  
  if(MaxSum <= 0){     //全是负数
  	printf("%d %d %d",0,arr[0],arr[K-1]);
  }else {
  	printf("%d %d %d",MaxSum,arr[FirstNum],arr[LastNum]);
  }
  
  free(arr);
  
  return 0;
}

int MaxSubseqSum(int K, int * arr,int *FirstNum, int *LastNum) {
  
  int MaxSum = 0;    //最大子列和
  int ThisSum = 0;   //当前子列和
  int i;
  for(i=0; i<K; ++i) {
    ThisSum += arr[i];
    if(ThisSum < 0) {
      ThisSum = 0;
    }
    if(ThisSum > MaxSum) {
      MaxSum = ThisSum;
      *LastNum = i;
    }
  }
  int tempSum = 0;
  for(i=*LastNum; i>=0; --i){    //向左累加找到开始下标
  	tempSum += arr[i];
  	if(tempSum == MaxSum) {
  	  *FirstNum = i;
  	  break;  
	  }
  }
  
  return MaxSum;
}

但测试结果还是不能全部通过







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值