【问题标题】:Maximum sum in a Subarray子数组中的最大和
【发布时间】:2016-09-26 14:56:05
【问题描述】:

给定一个由 N 个整数组成的数组。
数组的最大和是这个数组的一个非空连续子数组的元素的最大和。
例如数组[1, -2, 3, -2, 5]的最大和是6,因为子数组[3, -2, 5]的和是6,不可能得到更大的子数组和。
现在您可以从给定数组中删除不超过一个元素。这样做可以实现的结果数组的最大可能最大和是多少?

我正在用我自己的测试用例测试我的代码。我在 dev-c++ 上得到了正确的输出。 但是当我在线测试我的代码时,我得到了错误的答案。我无法找出问题所在。

#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
struct result{
    long long int start;
    long long int end;
    long long int sum;
}res;
long long int find_max(long long int a[],long long int n)
{
    long long int max=LLONG_MIN;
    long long int i;
    for(i=0;i<n;++i)
    {
        if(a[i]>max)
            max=a[i];
    }
    return max;
}
long long int max_sub(long long int a[],long long int n)
{
    long long int i;
    long long int min,sum1=0;
    struct result max,max_curr,*maxsub;
    maxsub=calloc(sizeof(res),n);
    max.sum=LLONG_MIN;
    max_curr=max;
    for(i=0;i<n;++i)
    {
        if(max_curr.sum<0)
        {
            max_curr.sum=a[i];
            max_curr.start=i;
            max_curr.end=i;
        }
        else
        {
            max_curr.sum+=a[i];
            max_curr.end=i;
        }
        if(max_curr.sum>max.sum)
        {
            max=max_curr;
        }
        maxsub[i]=max;
    }
    min=0;
    for(i=maxsub[n-1].start;i<=maxsub[n-1].end;++i)
    {
        if(a[i]<0)
        {
            if(min==0 || a[i]<min)
                min=a[i];
        }
    }
    sum1=maxsub[n-1].sum-min;
    return sum1;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--){
        long long int n,i;
        scanf("%lld",&n);
        long long int a[n];
        for(i=0;i<n;++i)
            scanf("%lld",&a[i]);
        long long int sum=0;
        sum=find_max(a,n);
        if(sum<=0)
        {
            printf("%lld\n",sum);
        }
        else
        {
            sum=max_sub(a,n);
            printf("%lld\n",sum);
        }

    }
    return 0;
}

【问题讨论】:

  • 您的意思是通过将其设为空来“删除一个元素”,还是通过删除该元素来缩小数组的大小?
  • 通过删除该元素来缩小数组的大小
  • 这是一个大小为 6 的数组:[1, 2, 3, -1, 5, 1]。当我运行你的程序时,我得到的结果是 12。但在我看来,结果应该是 11?
  • 测试您的代码以获取以下数组[ 1, -4, 3, -1, 1]。它会给出错误的结果3,但实际结果应该是4,这将通过从[1, -4, 3] 中删除-4 获得。
  • 这是来自正在进行的 CodeChef SnackDown 2016 预选赛的问题,请不要发布解决方案或帮助,因为这明显违反 CodeChef Code Of Conduct

标签: c max sub-array


【解决方案1】:

试试这个数组 {1, -100, 6, -50, 5}。 您正在以最大总和删除 subarray 中的最小元素,但根据您的问题,您可以从 original array 中删除最多一个元素,以便最大化其连续数组的总和,这就是为什么你得到一个错误的答案。

【讨论】:

    【解决方案2】:

    好吧,这不公平,人们一直在努力破解它。这是正在进行的 code-chef 在线竞赛的一部分,请关闭此线程。

    编辑:比赛现已结束,欢迎讨论:)

    【讨论】:

      【解决方案3】:

      请关闭此线程。 OP 正试图通过在此处发布问题来在正在进行的在线比赛中作弊。

      【讨论】:

        【解决方案4】:
        #include<stdio.h>
        #include<limits.h>
        long long int sum;
        long long int rightsum(long long int a[], long  int n, long int start, long int end) {
        
            long int i;
            long long int max_so_far=INT_MIN,max_ending_here=0;
            for(i=start;i<=end;i++)
            {
               max_ending_here = max_ending_here + a[i];
                if (max_so_far < max_ending_here)
                {
                    max_so_far = max_ending_here;
                }  
            }
            return max_so_far;
        }
        long long int leftsum(long long int a[], long long int n, long long int start, long long int end) {
        
            long int i;
            long long int max_so_far=INT_MIN,max_ending_here=0;
            for(i=end;i>=start;i--)
            {
              max_ending_here = max_ending_here + a[i];
                if (max_so_far < max_ending_here)
                {
                    max_so_far = max_ending_here;
                }  
            }
            return max_so_far;
        }
        long long int maxSum(long long int a[],long int n) {
        
            long long int sum = rightsum(a, n, 1, n - 1);
            long int i;
        
            for (i = 0; i < n; i ++) {
        
                long long int l = leftsum(a, n, 0, i - 1);
                long long int r = rightsum(a, n, i + 1, n - 1);
        
        
                if (((i > 0) && (i < n - 1)) && ( l>=0) && (r>0) && (l+r>sum)) {
        
                    sum = l+r;
                    if(sum<sum+a[i])
                    {
                        sum=sum+a[i];
                    }
        
                }
        
        
                else if ((i > 0) && (l >= r) && (l>sum)) {
                    sum = l;
        
                    if(sum<sum+a[i])
                    {
                        sum=sum+a[i];
                    }
        
                }
        
                else if ((i < n - 1) ) {
                    sum = r;
        
                    if(sum<sum+a[i])
                    {
                        sum=sum+a[i];
                    }
        
                }
            }
            return sum;
        }
        int main()
        {
            int t;
            long long i,n;
            long long int a[100000];
            scanf("%d",&t);
            while(t!=0)
            {
                scanf("%ld",&n);
                for(i=0;i<n;i++)
                {
                    scanf("%lld",&a[i]);
                }
                printf("%lld\n",maxSum(a,n));
                t--;
            }
            return 0;
        } 
        

        【讨论】:

        • 但这不是一种有效的方法。如何提高效率
        【解决方案5】:

        显然,您已经实现了 Kadane 算法来查找数组中的最大和子数组。 给定数组是:[1, -2, 3, -2, 5]
        Kadane 的结果:[3, -2 ,5 ]

        现在你要做的是:删除子数组中的最小元素,不幸的是这是不正确的。
        现在假设,给定数组是:[1, -2, 3, -2, 5, -33, 5]
        Kadane 的结果:[3, -2 ,5 ]
        您的输出: [3, 5] ,即 8

        但这里正确的答案是选择子数组 [3, -2, 5, -33, 5] 并消除'-33' 结果输出为: 11. (3+5+5-2)

        谢谢。
        PS:我对stackoverflow的第一个回答。这只是我讨论的一个例外,还有更多。
        祝你好运!

        【讨论】:

          【解决方案6】:

          为什么要从结果中减去最少的数字:

          /*min=0;
          for(i=maxsub[n-1].start;i<=maxsub[n-1].end;++i)
          {
              if(a[i]<0)
              {
                  if(min==0 || a[i]<min)
                      min=a[i];
              }
          }*/
          sum1=maxsub[n-1].sum;//-min;
          return sum1; // Works fine
          

          【讨论】:

          • 如语句所示,初始数组最大和为6,但如果去掉第四个元素(即-2),则数组[1, -2, 3, 5]将有子数组 [3, 5] 并且最大和的值将等于 8。问题中给出的解释
          • 因此我减去数组中最大的负数
          • 您在哪里进行在线测试?你能在测试中提供输入数字吗
          • 也许在线检查器只使用正数来检查您的程序。在这种情况下,它不会删除任何元素。
          猜你喜欢
          • 2015-02-09
          • 1970-01-01
          • 2019-11-20
          • 2017-12-28
          • 1970-01-01
          • 2013-06-04
          • 2021-01-21
          • 2015-09-15
          • 2020-01-22
          相关资源
          最近更新 更多