package Array; /** * 连续子数组的最大和 * 在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢? * 例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。(子向量的长度至少是1) * 思路: * F(i):以array[i]为末尾元素的子数组的和的最大值,子数组的元素的相对位置不变 F(i)=max(F(i-1)+array[i] , array[i]) res:所有子数组的和的最大值 res=max(res,F(i)) 如数组[6, -3, -2, 7, -15, 1, 2, 2] 初始状态: F(0)=6 res=6 i=1: F(1)=max(F(0)-3,-3)=max(6-3,3)=3 res=max(F(1),res)=max(3,6)=6 i=2: F(2)=max(F(1)-2,-2)=max(3-2,-2)=1 res=max(F(2),res)=max(1,6)=6 i=3: F(3)=max(F(2)+7,7)=max(1+7,7)=8 res=max(F(2),res)=max(8,6)=8 i=4: F(4)=max(F(3)-15,-15)=max(8-15,-15)=-7 res=max(F(4),res)=max(-7,8)=8 以此类推 最终res的值为8 */ public class Solution01 { public static void main(String[] args) { int[] arr = {6,-3,-2,7,-15,1,2,2}; System.out.println(FindGreatestSumOfSubArray(arr)); } public static int FindGreatestSumOfSubArray(int[] array) { if(array.length==0) return 0; int sum = array[0];//保存每组的和 int maxSum = array[0];//连续子数组最大和 //动态规划 for(int i = 1;i<array.length;i++){ sum = Math.max(sum+array[i],array[i]); maxSum = Math.max(sum,maxSum); } return maxSum; } }
class Solution { public: int FindGreatestSumOfSubArray(vector<int> array) { int max_sum = 0x80000000; int length = array.size(); if(length == 0)return 0; int *f = new int[length]; f[0] = array[0]; for(int i = 1; i < length; i++){ if(f[i-1] <= 0){ f[i] = array[i]; if(max_sum < f[i - 1]) max_sum = f[i - 1]; } else{ if(array[i] < 0){ if(max_sum < f[i - 1]) max_sum = f[i - 1]; } f[i] = f[i-1] + array[i]; } } if(max_sum < f[length - 1]){//需要考虑最后一个位置 max_sum = f[length - 1]; } return max_sum; } };
# 第一种算法:《算法导论(第四版)》--第四章:分治策略 def find_max_subarray(self, A, low, high): if low == high: return low, high, A[low] else: mid = (low + high) // 2 (left_low, left_high, left_sum) = self.find_max_subarray(A, low, mid) (right_low, right_high, right_sum) = self.find_max_subarray(A, mid + 1, high) (mid_low, mid_high, mid_sum) = self.find_max_cross_subarray(A, low, mid, high) if left_sum > right_sum and left_sum > mid_sum: return left_low, left_high, left_sum elif right_sum > left_sum and right_sum > mid_sum: return right_low, right_high, right_sum else: return mid_low, mid_high, mid_sum # 第二种:非递归方式求最大子数组
def find_max_subarray2(self, A): max_sum = -sys.maxint temp_sum = 0 start_index = 0 end_index = 0 for i in range(len(A)): if temp_sum < 0: temp_sum = 0 start_index = i end_index = i temp_sum += A[i] if temp_sum > max_sum: max_sum = temp_sum end_index = i return start_index, end_index, max_sum
#include <iostream.h> int maxSum(int* a, int n) { int sum=0; //其实要处理全是负数的情况,很简单,如稍后下面第3点所见,直接把这句改成:"int sum=a[0]"即可 //也可以不改,当全是负数的情况,直接返回0,也不见得不行。 int b=0; for(int i=0; i<n; i++) { if(b<0) //... b=a[i]; else b+=a[i]; if(sum<b) sum=b; } return sum; } int main() { int a[10]={1, -2, 3, 10, -4, 7, 2, -5}; //int a[]={-1,-2,-3,-4}; //测试全是负数的用例 cout<<maxSum(a,8)<<endl; return 0; }
class Solution { public: int maxSubArray(int A[], int n) { if(n <= 0){ return 0; }//if // 最大和 int max = A[0]; // 当前最大和 int cur = 0; for(int i = 0;i < n;++i){ // 一旦当前最大和小于0就重置为0,一个负数只能使最大和变小 if(cur < 0){ cur = 0; }//if cur += A[i]; if(cur > max){ max = cur; }//if }//for return max; } };