一种寻找数组中和为最大的子数组的算法



import java.util.Arrays;

/**
 *
 * 
 * 一个寻找数组中和为最大的子数组的算法
 * 《算法导论(第3版)》P38
 * 算法思想:一个数组的最大子数组在该数组中的位置对于该数组的中点
 * 来说有三种情况,1是在中点的左边,2是在右边,3是穿过中点。1,2两
 * 种情况可以看成是有问题的一个子问题,利用递归的方法求解。第3种情
 * 况可以在一个线性的时间内完成计算
 * 算法复杂度:Θ(nlgn)
 * */
public class FindMaximumSubarray {
    
    //寻找一个穿过中点的最大子数组
    public static int[] findMaxCrossingSubarray(int[] a, int low, int mid, int high){
        int[] result = new int[3]; //保存结果,包括子数组的头尾及和值
        int leftSum = a[mid];
        int sum = 0;
        result[0] = mid;
        for(int i=mid;i>=low;i--){
            sum = sum + a[i];
            if(sum > leftSum){
                leftSum = sum;
                result[0] = i;
            }
        }
        int rightSum = a[mid+1];
        sum = 0;
        result[1] = mid +1;
        for(int i=mid+1;i<=high;i++){
            sum = sum + a[i];
            if(sum > rightSum){
                rightSum = sum;
                result[1] = i;
            }
        }
        if(leftSum+rightSum>leftSum)
            result[2] = leftSum + rightSum;
        else
            result[2] = leftSum;
        return result;
    }
    
    public static int[] findMaximumSubarray(int[] a, int low, int high){
        int[] result = new int[3]; //保存结果,包括子数组的头尾及和值
        if(low == high){
            result[0] = result[1] = low;
            result[2] = a[low];
            return result;
        }else{
            int[] leftResult ;
            int[] rightResult;
            int[] midResult;
            //寻找最大子数组的三种情况
            leftResult = findMaximumSubarray(a,low,(low+high)/2); //第1种情况
            rightResult = findMaximumSubarray(a,(low+high)/2+1,high); //第2种情况
            midResult = findMaxCrossingSubarray(a,low,(low+high)/2,high); //第3种情况
            
            //将三种情况的最终结果进行比较
            if(leftResult[2] >= rightResult[2] && leftResult[2] >= midResult[2])
                return leftResult;
            else if(rightResult[2] >= leftResult[2] && rightResult[2] >= midResult[2])
                return rightResult;
            else
                return midResult;
        }
        
    }
    
    //测试算法的准确性
    //结果为[7,10,43]
    public static void main(String[] args){
        int[] a={13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7};
        int[] result = findMaximumSubarray(a,0,a.length-1);
        System.out.println(Arrays.toString(result));
         System.out.println(Arrays.toString(findMaxCrossingSubarray(a,0,(0+a.length-1)/2,a.length-1)));
    }
    
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值