求子数组之和最大值(包括循环)

编程珠玑中给出了n*logn的解法,很有参考价值。O(n)的扫描方法,用到了前面分析的若干策略:

1) 从某个位置开始,到i位置结束的sum的计算方法是max_ending_here + array[i]

2)以往的最大值是max_sofar,要和到当前结束点的最大值进行比较取其大者

3)如果max_ending_here + array[i]的值小于array[i]的值,说明max_ending_here是负值,应该从新计数

4)如果max_sofar的值==max_ending_here的值,说明获得了一个最大值,应该更新开始和结束的位置信息

--------------

对于循环数组,需要计算好一下几个方面的内容:

1)要计算好数组的index

2)如果是第二轮了,有重新开始计数了,那么就可以退出了,因为后面的情况已经计算过了(或许也不对,因为从这个位置开始,再经过循环数组可能产生新的数组,和第一轮可能不一样?)

3)如果数组整体和大于0,那么可能会循环不停下来,因为不断循环,最大值不断加大,这是需要有一个终止条件,比如,循环2次终止

程序代码如下:

#include <stdio.h>
template<typename T>
T Max(const T& left, const T& right) {
  if (left < right) {
    return right;
  } else {
    return left;
  }
}
int MaxSum(int array[], int begin, int end, int* max_start, int* max_end) {
  *max_start = 0;
  int max_sofar = 0x80000001;
  printf("max_sofar = %d\n", max_sofar);
  int max_ending_here = 0;
  int start = 0;
  for (int i = begin; i <= end; ++i) {
    max_ending_here = Max(max_ending_here + array[i], array[i]);
    if (max_ending_here == array[i]) {
      start = i;
    }
    max_sofar = Max(max_sofar, max_ending_here);
    if (max_sofar == max_ending_here) {
      *max_start = start;
      *max_end = i;
    }
  }
  return max_sofar;
}

int CircleArrayMaxSum(int array[], int begin, int end, int* max_start, int* max_end) {
  int i = 0;
  bool next_round = false;
  int array_size = end - begin + 1;
  int max_sofar = 0x80000000;
  int max_ending_here = 0;
  int start = 0;
  while (true) {
    if (i > array_size) {
      next_round = true;
    }
    max_ending_here = Max(max_ending_here + array[i % array_size], array[i % array_size]);
    if (max_ending_here == array[i % array_size]) {
      start = i % array_size;
      if (next_round) {
        break;
      }
    }
    max_sofar = Max(max_sofar, max_ending_here);
    if (max_sofar == max_ending_here) {
      *max_start = start;
      *max_end = i % array_size;
    }
    i++;
    if (i  >= 2 * array_size) {
      break;
    }
  }
  return max_sofar;
}
        
    
int main(int argc, char** argv) {
  int array[] = {-2, 5, 3, -6, 4, -8, 6};
  //int array[] = {-9, -2, -3, -5, -3};
  //  int array[] = {0, -1, 3, 5, -1, 2};
  int max_start = -1;
  int max_end = -1;
  int array_length = sizeof(array) / sizeof(int);
  int max_sum = MaxSum(array, 0, array_length - 1, &max_start, &max_end);
  printf("no circle: max_sum = %d, start= %d, end = %d\n", max_sum, max_start, max_end);
  max_sum = CircleArrayMaxSum(array, 0, array_length - 1, &max_start, &max_end);
  printf("no circle: max_sum = %d, start= %d, end = %d\n", max_sum, max_start, max_end);
}
  


参考文献:

编程之美P183 2.14

编程珠玑 第8章算法设计技术

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值