博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
分治策略求解数组的最大连续子数组的和
阅读量:4628 次
发布时间:2019-06-09

本文共 3196 字,大约阅读时间需要 10 分钟。

对于一个数组,尽可能地划分成两半(二分),加和最大的连续字数组或者在左边,或者在右边,或者跨越中间,一部分在左边,一部分在右边。

那么只要求出左半段数组的加和最大的连续子数组的和,求出右半段数组的加和最大的连续子数组的和,求出跨越中间的最大连续字数组的和,只要通过三者判断求出最大的那么就是整个数组最大的连续子数组的和。

那么找出左半段和右半段的最大连续子数组的和其实就是比原问题规模更小的一个问题,因此对于左半段和右半段求解加和最大的连续子数组的和可以通过递归求得。

下面给出具体实现:、

首先是调用接口:

1 /** 2      * 该函数是找出数组中连续子数组的最大和(连续的数组段 3      * -1,3,-2 , 4 ,5,10,-1那么数组的连续子数组的和的最大值就是20,[3,-2 , 4 ,5,10] 4      * 为所求 5      * 想法:对一个数组划分为尽可能相等的两段(二分),加和最大的一段或者在左边 6      * 或者在右边,或者是跨中间的,那么我们只需要找出左边最大的子数组的和和右边最大的子数组的和 7      * 最后找出跨中间最大的子数组的和,然后在这三个子数组中和最大的一个肯定就是整个数组中是最大 8      * 那么对于左边数组求最大和其实就是原问题的子问题,也是对左边数组进行划分成两半,然后对于左边 9      * 数组分析和原来分析一样,也是可能最左边,或者在右边,或者在中间,因此一直递归即可找到连续10      * 子数组的最大加和11      * @param array 12      * @return13      * @throws Exception 14      */15     public static int findSumMax(int[] array){16         if (array == null) {17             throw new NullPointerException("数组空指针异常");18         }else if (array.length == 0) {19             return 0;20         }else {21             return findMaxFromLeftMiddleRight(array, 0, array.length - 1);22         }23     }

 

然后就是对数组分段之后求左右段和跨中间段的加和最大的连续子数组的和,然后进行比较,求出最大的就是整个数组最大的连续子数组的最大和

1 /** 2      * 找出左半段,右半段,中间段的最大值 3      * @param array 4      * @param left 5      * @param right 6      * @return 7      */ 8     private static int findMaxFromLeftMiddleRight(int[] array , int left , int right){ 9         if (left == right) {10             return array[left] > 0 ? array[left] : 0;11         }12         int middle = (left + right) / 2;13         //找出左边的最大值14         int maxL = findMaxFromLeftMiddleRight(array, left, middle);15         //找出右边的最大值16         int maxR = findMaxFromLeftMiddleRight(array, middle + 1, right);17         //找出跨越中间的最大值18         int maxMid = findMaxCrossMiddle(array, left, right);19         return (maxL > maxR ? maxL : maxR) > maxMid 20                 ? (maxL > maxR ? maxL : maxR) : maxMid;21     }

 

最后的重点就是找出跨越分界的两端的连续子数组的最大加和

1 /** 2      * 找出跨越中间的数组的最大连续子数组的最大加和 3      * 想法:找出中间的位置,从左边一段的最右开始往回找,直到找到最大值 4      * 再从右边一段的最左往右找,直到找到最大值,然后两个和加起来就是跨 5      * 越中间的连续子数组的最大值 6      * @param array 7      * @param left 8      * @param right 9      * @return10      */11     private static int findMaxCrossMiddle(int[] array , int left , int right){12         if (left == right) {13             return array[left] > 0 ? array[left] : 0;14         }15         //尽可能找出数组中间16         int mid = (left + right) / 2;17         int maxL = 0;18         //sum用于记录左半段数组的加和19         int sumL = 0;20         //从中间往左边找,找到最大值21         for (int i = mid; i >= left; i--) {22             //一旦左半边的加和比已缓存的左边最大值大,那么就更新最大值23             if ((sumL = sumL + array[i])> maxL) {24                 maxL = sumL;25             }26         }27         int maxR = 0;28         int sumR = 0;29         //从中间往右边找,找到最大值30         for (int j = mid + 1; j <= right; j++) {31             if ((sumR = sumR + array[j]) > maxR) {32                 maxR = sumR;33             }34         }35         return (maxL+maxR);36     }
1 //测试程序如下2     public static void main(String[] args) {3         int[] array = {-1,3,-2 , 4 , 5,10,-1 , 6,-4,3,-8};4         System.out.println(MyUtil.findSumMax(array));5     }

可求得测试结果为25。

 

转载于:https://www.cnblogs.com/liucaihao/p/5583268.html

你可能感兴趣的文章
产品功能对标 - 服务授权管理
查看>>
vue+element-ui实现表格checkbox单选
查看>>
Xcode10 library not found for -lstdc++ 找不到问题
查看>>
Mysql 8.0.13如何重置密码
查看>>
发布功能完成
查看>>
excel 合并单元格
查看>>
How to Create Modifiers Using the API QP_MODIFIERS_PUB.PROCESS_MODIFIERS
查看>>
待飞笔记(第一天 )
查看>>
解惑好文:移动端H5页面高清多屏适配方案
查看>>
traefik添加多证书
查看>>
忽略UserInterfaceState.xcuserstate
查看>>
ReactNative--Flexbox布局
查看>>
java实现读取文件大全
查看>>
[Cordova] 无法显示Alert视窗
查看>>
借助过度区选择阈值
查看>>
python+rabbitMQ实现生产者和消费者模式
查看>>
“模态”对话框和“后退”按钮
查看>>
Geohash距离估算
查看>>
Demon_背包系统(实现装备栏,背包栏,可以切换装备)
查看>>
记录:一次数据库被恶意修改配置文件的问题
查看>>