多种方法求最大字段和js实现

参考链接:最大子段和详解 (各种复杂度)_风的记忆-CSDN博客_最大子段和

暴力求解(穷举、枚举)法O(n^2)

function getMaxSumEnum (arr) { 
    var max = arr[0];
    var sum = 0;
    for(var i=0; i<arr.length; i++) {
      sum = 0;
      for(var j=i; j<arr.length; j++) {
        sum += arr[j];
        if (sum > max) {
          max = sum;
        }
      }
    }
  console.log(max);
  return max;
}
var arr = [-1, 2, -3, 4, -1, 5];
getMaxSumEnum(arr);
// 输出
8

分支递归法 O(nlogn)

将数组划分为左右两部分,则最大子段和可能在三处出现:

用n表示最大索引,即len(arr)-1

  • 左半部
    • [0, n/2]
  • 右半部
    • [n/2+1, n]
  • 跨越左右边界的部分
    • 起点位于[0, n/2], 终点位于[n/2+1, n]
    • 这种情况一定包含n/2和n/2+1这2个位置
    • 可以使用枚举法
    • 以n/2为终点,往左移动扩张,求出和最大的一个leftMax
    • 以n/2+1为起点,往右移动扩张,求出和最大的一个rightMax
    • leftMax + rightMax是这种情况可能的最大值

递归的终止条件是:left == right。

function getMaxSumDevideConquer (arr, left, right) { 
    // 思想:
    // 将序列划分为左右两部分,则最大子段和可能在三处出现:
    // 左半部、右半部以及跨越左右边界的部分。
    // 递归的终止条件是:left == right。
  
      if (left == right) {
        return arr[left];
      }
      // 一半
      var half = Math.floor((left + right) / 2);
      // 左侧最大子段和 问题1:这里的左侧为什么也包含half这个中间值
      var leftValue = getMaxSumDevideConquer(arr, left, half);
      // 右侧最大字段和  
      var rightValue = getMaxSumDevideConquer(arr, half + 1, right);
      // 中间最大字段和
      var leftMax = arr[half];
      var leftSum = arr[half];
      for (i = half - 1; i >= left; i--) {
        // 问题2:这里的左侧为什么也包含half这个中间值
        leftSum += arr[i];
        if (leftSum > leftMax) {
          leftMax = leftSum;
        }
      }

      var rightMax = arr[half + 1];
      var rightSum = arr[half + 1];
      for (var i = half + 1 + 1; i <= right; i++) {
        // 问题3:这里的左侧为什么从half+1+1开始 
        rightSum += arr[i];
        if (rightSum > rightMax) {
          rightMax = rightSum
        }
      }
      console.log(leftValue, rightValue, leftMax + rightMax);
      return Math.max(leftValue, rightValue, leftMax + rightMax);
}

var arr = [-1, 2, -3, 4, -1, 5];
var max = getMaxSumDevideConquer(arr, 0, arr.length - 1)
console.log(max)
// 输出 
-1 2 1
2 -3 -1
4 -1 3
4 5 8
2 8 7
8

动态规划法O(n)(TODO)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值