求一个数组中的最大子段和

最大子段和: 数组中子段(连续的n个元素)元素累加最大的和

思路:

利用动态规划。

最大子段和构成:最大子段和对应的子段的左右相邻的子段的和一定是小于等于0的,否则,该子段的和不是最大子段和。

因此,从头至尾累加数组中元素,若出现小于0,当前子段对最大子段和为负贡献,则舍弃,从下一个元素开始累加。

max_sum 为当前最大子段和

sum为当前子段的和

a[i] 为当前元素

则:  

 sum  +=  a[i];

分以下情况:

if (sum > max_sum)  //当前子段和为最大子段和

   max_sum = sum;

if (sum < 0)  //当前子段和为负,即右部序列和<0,则重新累计

  sum = 0; 


特殊情况,若当前数组中均为负数,则最大的那个数即为最大子段和。


===========================================参考代码=============================================

#include<iostream>
#include<string>
using namespace std;
// begin, end 用来记录最大子段和对应子段的起始和结束下标
int MaxSubSegSum(int arr[], int size, int &begin, int &end) {
  int max_sum = *arr;
  int sum = 0;
  int tmp_begin = 0;
  begin = 0;
  end = 0;
  bool all_less_0 = true;  // 记录是否为全负数的情况
  for (int i = 0; i != size; ++i) {
    if(all_less_0 && arr[i] < 0) {  
      if (arr[i] > max_sum) {
        max_sum = arr[i];
        begin = end = i;
      }   
      continue;
    }
    if (all_less_0) {
      all_less_0 = false;
    }   
    sum += arr[i];
    if (sum > max_sum) {
      max_sum = sum;
      end = i;
      begin = tmp_begin;
    }   
    if (sum < 0 && i != (size - 1)) {
      sum = 0;
      tmp_begin = i+1;
    }   
  }
  return max_sum;
}

int main() {
  int arr[] =
                  {1, 2, -10, 5, -4, 4, 3, -9, 1}; 
        //         {1, 2, -10, 5, -4, 4, 3, -9, 100};
        //         {-10, -4, -9, -3, -22};
    int size = sizeof(arr) / sizeof(*arr);
    int start, end;
    int max = MaxSubSegSum(arr, size, start, end);
    cout << "数组内容: ";
    for (int i = 0; i != size; ++i) {
      cout << arr[i] << " ";
    }
    cout << endl <<"最大子段和为: " << max << endl
         << "起始下标: " << start << endl
         << "结束下标: " << end << endl
         << "相应子段为: ";
    for (int i = start; i <= end; ++i ) {
      cout << arr[i] << " ";
    }

  return 0;
}



            原创文章,转载请注明: 转载自     编程小径

          本文链接地址: http://blog.csdn.net/imbing/article/details/8217630



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值