最大连续子序列和问题

题目描述

给定整数序列A1,A2,…,An,对其所有连续子序列求和,寻找累加和最大的序列。如果所有的整数都是负的,那么最大连续子序列的和为0。

输入格式

输入包括多组测试数据,每组测试数据一行,每行第一个为正整数n(0 < n <= 100000),表示序列长度,紧跟着n个整数,Ai
(-1001<Ai < 1001),表示序列每个元素,各个整数之间用空格隔开。

输出格式

针对每组测试数据,输出最大连续子序列的和,以及该最大连续子序列的起止位置。当最大连续子序列的长度为0时,序列的起止位置都输出为-1。如果有多个连续子序列的值为最大值,输出第一个连续子序列。

多组输出用换行隔开

输入样例 复制

6 -2 11 -4 13 -5 2
1 -1

输出样例 复制

20 1 3

0 -1 -1

#include <iostream>
#include<cmath>
#define ll long long
using namespace std;
const int Max=1e5+5;
int a[Max];
int main()
{
    int n;
    while(cin>>n){
        for(int i=0;i<n;i++)scanf("%d",&a[i]);
        int maxsum,maxhere;
        maxsum=maxhere=a[0];
        int beg=0,end=0,newbeg=0;
        for(int i=1;i<n;i++){
            if(maxhere<=0){//目前sum<=0时换新开头
                maxhere=a[i];
                newbeg=i;
            }
            else {
                maxhere+=a[i];
                }
            if(maxhere>maxsum){
                maxsum=maxhere;//记录最大值以及首尾下标
                beg=newbeg;
                end=i;
            }
        }

        if(maxsum<=0)printf("0 -1 -1\n");
        else printf("%d %d %d\n",maxsum,beg,end);
    }


    return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我将扮演 CSDN 开发的 C知道,我会尽力回答你的问题。对于你的第一个问题,以下是我的回答: 暴力穷举法(3层循环): 我们可以使用三层循环来枚举所有可能的连续子序列,然后计算它们的和,最后找到最大的和。具体实现如下: int maxSubArraySum(int arr[], int n) { int max_sum = INT_MIN; for (int i = 0; i < n; i++) { for (int j = i; j < n; j++) { int sum = 0; for (int k = i; k <= j; k++) { sum += arr[k]; } if (sum > max_sum) { max_sum = sum; } } } return max_sum; } 优化穷举法(2层循环): 我们可以使用两层循环来枚举所有可能的连续子序列,然后计算它们的和,最后找到最大的和。具体实现如下: int maxSubArraySum(int arr[], int n) { int max_sum = INT_MIN; for (int i = 0; i < n; i++) { int sum = 0; for (int j = i; j < n; j++) { sum += arr[j]; if (sum > max_sum) { max_sum = sum; } } } return max_sum; } 问题转化—等效子问题求解的动态规划法(1层循环): 我们可以使用动态规划来解决这个问题,具体来说,我们定义一个数组 dp,其中 dp[i] 表示以第 i 个元素结尾的最大子序列和。然后,我们可以使用以下递推公式来计算 dp[i]: dp[i] = max(dp[i-1] + arr[i], arr[i]) 最后,我们可以遍历 dp 数组,找到其中的最大值即可。具体实现如下: int maxSubArraySum(int arr[], int n) { int max_sum = INT_MIN; int dp = arr[0]; for (int i = 1; i < n; i++) { dp = max(dp + arr[i], arr[i]); max_sum = max(max_sum, dp); } return max_sum; } 分治法(递归求解): 我们可以使用分治法来解决这个问题,具体来说,我们将数组分成两个部分,分别求出左半部分的最大子序列和、右半部分的最大子序列和以及跨越中点的最大子序列和,然后取这三个值的最大值即可。具体实现如下: int maxSubArraySum(int arr[], int l, int r) { if (l == r) { return arr[l]; } int m = (l + r) / 2; int left_max = maxSubArraySum(arr, l, m); int right_max = maxSubArraySum(arr, m+1, r); int cross_max = arr[m]; int sum = arr[m]; for (int i = m-1; i >= l; i--) { sum += arr[i]; cross_max = max(cross_max, sum); } sum = arr[m+1]; for (int i = m+2; i <= r; i++) { sum += arr[i]; cross_max = max(cross_max, sum); } return max(left_max, max(right_max, cross_max)); } int maxSubArraySum(int arr[], int n) { return maxSubArraySum(arr, 0, n-1); } 希望这些回答能够帮助你!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值