逐步优化求解最大子序列和

系统 1472 0

求解最大子序列和

tag: 数据结构与算法


最大子序列和问题:

给定序列A 1 , A 2 ,... A N , 求最大的子序列和。
例如 :
  对于序列4, -3, 5, -2, -1, 2, 6, -2, 最大序列和为11(4 -3 + 5 - 2 - 1 + 2 + 6)

算法一:

利用两个循环,第一个循环把序列遍历一遍,第二个循环则从A i 累加到A N ,每加一次判断一下是否大于之前的最大子序列和:

    
      int maxSubsequenceSum1 (const int arr[], int n) {
  int maxSum = 0;
  int temp;

  for (int i = 0; i < n; i++) {
    temp = 0;

    for (int j = i; j < n; j++) {
      temp += arr[j];
      if (temp > maxSum)
	maxSum = temp;
    }
  }

  return maxSum;
}
    
  

时间复杂度:O(n 2

算法二:

首先把序列从中间一分为二, 则最大子序列和的存在有三种情况:

  1. 全在左边的子序列
  2. 全在右边的子序列
  3. 处在中间
    对于第一和第二种情况,只需要递归调用求解函数,对于第三种情况则要分别求出从中间出发,向左边和向右边各自的最大子序列和。
    
      int max(int a, int b, int c) {
  int max;

  if (a > b)
    max = a;
  else 
    max = b;

  if (c > max)
    max = c;

  return max;
}

int maxSubsequenceSum2 (const int arr[], int begin, int end) {
  int maxLeftSum, maxRightSum, maxLeftCenterSum, maxRightCenterSum, center, temp;

  if (begin >= end) {
    if (arr[begin] > 0)
      return arr[begin];
    else
      return 0;
  }

  center = (begin+end)/2;
  maxLeftSum = maxSubsequenceSum2(arr, begin, center);
  maxRightSum = maxSubsequenceSum2(arr, center+1, end);

  maxLeftCenterSum = 0;
  temp = 0;
  for (int i = center; i >= begin; i--) {
    temp += arr[i];

    if (temp > maxLeftCenterSum)
      maxLeftCenterSum = temp;
  }

  maxRightCenterSum = 0;
  temp = 0;
  for (int i = center+1; i <= end; i++) {
    temp += arr[i];

    if (temp > maxRightCenterSum)
      maxRightCenterSum = temp;
  }

  return max(maxLeftSum, maxRightSum, (maxLeftCenterSum+maxRightCenterSum));
}
    
  

时间复杂度:O(nlogn)

算法三:

累加序列,若发现当前序列和大于之前最大序列和,则替换.若发现当前序列和小于0,则将当前序列和置换成0,相当于把前面的序列都舍弃掉.

    
      int maxSubsequenceSum3(int arr[], int n) {
  int tempSum = 0, maxSum = 0;

  for (int i = 0; i < n; i++) {
    tempSum += arr[i];
    if (tempSum < 0)
      tempSum = 0;
    if (tempSum > maxSum)
      maxSum = tempSum;
  }

  return maxSum;    
}
    
  

时间复杂度:O(n)

逐步优化求解最大子序列和


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论