最大子段和问题
/** * 问题: 给定n个整数(可能为负数)组成的序列a[1],a[2],a[3],…,a[n], * 求该序列如a[i]+a[i+1]+…+a[j]的子段和的最大值。 * 当所给的整数均为负数时定义子段和为0,依此定义,所求的最优值为: * Max{0,a[i]+a[i+1]+…+a[j]},1<=i<=j<=n * 例如,当(a[1],a[2],a[3],a[4],a[5],a[6])=(-2,11,-4,13,-5,-2)时, * 最大子段和为20。 */ var a = [-2, 11, -4, 13, -5, -2]; console.log(maxsub(a)); // 分治法 function maxsub(a) { function _maxsub(a, left, right) { var sum, left_sum, right_sum; var left_max, right_max; var i, center = Math.floor((left+right)/2); if (left === right) { return a[left] > 0 ? a[left] : 0; } left_sum = _maxsub(a, left, center); right_sum = _maxsub(a, center+1, right); sum = 0; left_max = 0; for (i = center; i >= left; i--) { sum += a[i]; if (sum > left_max) { left_max = sum; } } sum = 0; right_max = 0; for (i = center + 1; i <= right; i++) { sum += a[i]; if (sum > right_max) { right_max = sum; } } sum = right_max + left_max; if (sum < left_sum) { sum = left_sum; } if (sum < right_sum) { sum = right_sum; } return sum; } return _maxsub(a, 0, a.length-1); }
// 动态规划法 function maxsub(a) { var max, n = a.length, i, b = new Array(n); max = b[0] = a[0]; for (i = 1; i < n; i++) { b[i] = b[i-1]>0 ? b[i-1]+a[i] : a[i]; if (b[i]>max) { max = b[i]; } } return max; }
最优解:
function maxsub(a) { var thisSum, maxSum; thisSum = maxSum = 0; for (var j = 0; j < a.length; j++) { thisSum += a[j]; if (thisSum > maxSum) { maxSum = thisSum; } else if (thisSum < 0) { thisSum = 0; } } return maxSum; }