求最大子数组的三种方法

(1)暴力求解,运行时间是n²

        int ans = -1000000;  
        for(int i=0; i<n; i++)  
        {  
            int sum = 0;  
            for(int j=i; j<n; j++)  
            {  
                sum += nums[j];  
                if(sum > ans)  
                {  
                    ans = sum;  
                }  
            }  
        }  
        return ans;  

  

(2)分治策略,运行时间是nlogn

使用分治技术意味着我们要将子数组划分为两个规模尽量相等的子数组,也就是找到子数组的中央位置(比如mid),然后考虑求解两个子数组A[low..mid]和A[mid+1..high]。A[low..high]的任意连续子数组A[i..j]所处的位置必然是以下三种情况之一:

(a)完全位于子数组A[low..mid]中,因此low≤i≤j≤mid

(b)完全位于子数组A[mid+1..high]中,因此mid≤i≤j≤high

(c)跨越了中点,因此low≤i≤mid≤j≤high

所以我们需要求解这三种情况的最大子数组,然后再取最大值。A[low..mid]和A[mid+1..high]可以递归求解,剩下的就是训中跨越中点的最大子数组

Find-MAX-CROSSING-SUM(a, low, mid, high)

    //求中点左边的最大值和最大位置

    int maxLeft;//记录左边的最大位置
    int maxSumLeft=-10000;//记录左边的最大和
    int sumLeft=0;
    for (int i = mid; i >= low; i--)
    {
        sumLeft += a[i];
        if (sumLeft > maxSumLeft)
        {
            maxSumLeft = sumLeft;
            maxLeft = i;
        }
    }
    //求中点右边的最大值和最大位置
    int maxRight=mid+1;//记录右边的最大位置
    int maxSumRight = -10000;//记录右边的最大和
    int sumRight = 0;//记录右边子数列的和
    for (int i = mid+1; i <= high; i++)
    {
        sumRight += a[i];
        if (sumRight > maxSumRight)
        {
            maxSumRight = sumRight;
            maxRight = i;
        }

    }

return (maxLeft , maxRight,maxSumLeft+maxSumRight );

求解最大子数组的分治算法如下:

FIND-MAXIMUM-SUBARRAY(A, low, high)

if high==low

    return (low,high,A[low])

else mid =(low+high)/2

    (left-low, left-high,left-sum) = FIND-MAXIMUM-SUBARRAY(A, low, mid)

    (right-low, right-high,right-sum) = FIND-MAXIMUM-SUBARRAY(A, mid+1, high)

    (cross-low, cross-high, cross-sum) = Find-MAX-CROSSING-SUM(A, low, mid, high)

    返回三种的最大值

(3)贪心算法,运行时间是n

    将子串和为负数的子串丢掉,只留和为正的子串

  1.         int ans = -1000000;  
  2.         int sum = 0;  
  3.         for(int i=0; i<n; i++)  
  4.         {  
  5.             sum += nums[i];  
  6.             if(sum > ans)  
  7.             {  
  8.                 ans = sum;  
  9.             }  
  10.             if(sum < 0)  
  11.             {  
  12.                 sum = 0;   //子串和为负数,丢掉  
  13.             }  
  14.         }  
  15.         return ans;  

  • 8
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值