分治算法求解最大连续子数组
2018-03-19 00:04
267 查看
分治策略求解最大连续子数组问题:原理:如果想要通过递归进行实现,就必须将数组进行子数组的划分,通过子数组划分,出现三种情况可能包含最大子数组,一种是在左边的子数组,一种是在右边的子数组,另一种是跨越中间量的子数组,对于左右子数组便又变成了求解其最大子数组(递归),而跨越中间的子数组需要单独进行遍历求取最大子数组一直存在理解上的疑惑:如何确定递归得到的就是最大子数组?通过正向进行递归计算如下:假定存在如下数组,下列的步骤为依次进行递归的情况:
从上表的递归情况进行分析:最小子数组里面已经比较得到了最大连续的子数组,比如(A,1,2) (A,3,4) (A,1,2,4)中已经获取到最大数组,其作为A1,8的子数组左半边已经获取到最大子数组(可能为(A1,4)跨越中点的,也可能其他半边),而(A,1,4,8)只需要再进行跨越中点的子数组获取最大就可以和前面已经得到的结果即(A1,4) (A,5,8)进行对比,然后再跟跨越8的中点的最大子数组对比,就能得到结果了这样理解后,从正面也想通了分治策略用递归实现的原理。a,1,16-> (a,1,8) and (a,9,16) and (a 1,8,16)中取最大连续子数组,再进行递归Java实现分治求解最大连续子数组:public class MaxContinuousArray {
public static int[] getMaxConArray(int left,int right,int[] arr){
int mid = (left+right)/2;
if(left==right){
return new int[]{left,right,arr[left]};
}
int[] leftMaxValue=new int[2];
int[] rightMaxValue=new int[2];
int[] midMaxValue=new int[2];
leftMaxValue=getMaxConArray(left, mid, arr);
rightMaxValue=getMaxConArray(mid+1, right, arr);
midMaxValue=getMidConArray(left, right, mid, arr);
if(leftMaxValue[2]>rightMaxValue[2]&&leftMaxValue[2]>midMaxValue[2]){
return leftMaxValue;
}else{
if(rightMaxValue[2]>midMaxValue[2]){
return rightMaxValue;
}else{
return midMaxValue;
}
}
}
private static int[] getMidConArray(int left,int right,int mid,int[] arr){
int leftSubMaxValue=0;
int leftSubMaxInd=mid;
int leftSubSum=0;
int rightSubMaxValue=0;
int rightSubMaxInd=mid;
int rightSubSum=0;
for(int i=1;i<mid-left+1;i++){
leftSubSum+=arr[mid-i];
if(leftSubMaxValue<leftSubSum){
leftSubMaxValue=leftSubSum;
leftSubMaxInd=mid-i;
}
}
for(int i=1;i<right-mid+1;i++){
rightSubSum+=arr[mid+i];
if(rightSubMaxValue<rightSubSum){
rightSubMaxValue=rightSubSum;
rightSubMaxInd=mid+i;
}
}
return new int[]{leftSubMaxInd,rightSubMaxInd,leftSubMaxValue+rightSubMaxValue+arr[mid]};
}
}
A1 | A2 | A3 | A4 | A5 | A6 | A7 | A8 | A9 | A10 | A11 | A12 | A13 | A14 | A15 | A16 |
13 | -3 | -25 | 20 | -3 | -16 | -23 | 18 | 20 | -7 | 12 | -5 | -22 | 15 | -4 | 7 |
A,1,16 | |||||||||||||||
A,1,8 | |||||||||||||||
A,1,4 | |||||||||||||||
A,1,2 | 1,1,A1 | 13 | |||||||||||||
< 4000 /p> | A,3,4 | 4,4,A4 | 20 | ||||||||||||
A,1,2,4 | 1,4,7 | 10 | |||||||||||||
A,5,8 | |||||||||||||||
A,5,6 | |||||||||||||||
A,7,8 | |||||||||||||||
A,5,6,8 | |||||||||||||||
A,1,4,8 |
public static int[] getMaxConArray(int left,int right,int[] arr){
int mid = (left+right)/2;
if(left==right){
return new int[]{left,right,arr[left]};
}
int[] leftMaxValue=new int[2];
int[] rightMaxValue=new int[2];
int[] midMaxValue=new int[2];
leftMaxValue=getMaxConArray(left, mid, arr);
rightMaxValue=getMaxConArray(mid+1, right, arr);
midMaxValue=getMidConArray(left, right, mid, arr);
if(leftMaxValue[2]>rightMaxValue[2]&&leftMaxValue[2]>midMaxValue[2]){
return leftMaxValue;
}else{
if(rightMaxValue[2]>midMaxValue[2]){
return rightMaxValue;
}else{
return midMaxValue;
}
}
}
private static int[] getMidConArray(int left,int right,int mid,int[] arr){
int leftSubMaxValue=0;
int leftSubMaxInd=mid;
int leftSubSum=0;
int rightSubMaxValue=0;
int rightSubMaxInd=mid;
int rightSubSum=0;
for(int i=1;i<mid-left+1;i++){
leftSubSum+=arr[mid-i];
if(leftSubMaxValue<leftSubSum){
leftSubMaxValue=leftSubSum;
leftSubMaxInd=mid-i;
}
}
for(int i=1;i<right-mid+1;i++){
rightSubSum+=arr[mid+i];
if(rightSubMaxValue<rightSubSum){
rightSubMaxValue=rightSubSum;
rightSubMaxInd=mid+i;
}
}
return new int[]{leftSubMaxInd,rightSubMaxInd,leftSubMaxValue+rightSubMaxValue+arr[mid]};
}
}
相关文章推荐
- 动态规划求解连续子数组最大和问题(应该是新的描述方法?)
- 连续子数组最大和或最大子段和的求解算法及其正确性
- 求解连续子数组乘积的最大值
- golang动态规划求解最大连续子数组和
- 动态规划--求最大连续子数组的和(Python实现)&求解最大连续乘积字串(Python实现)
- 求解最大连续子数组问题
- 分治算法实现最大连续子数组和
- 编程珠玑第八章——分治算法求解数组中的最大的连续和
- 求解最大连续子数组的算法
- 最大连续子数组和问题
- 最大连续子数组和
- 数组中最大最小值的蛮力法和二分法求解
- C#求数组中和最大的连续子数组
- 连续子数组的最大和
- 算法笔记_043:最大连续子数组和(Java)
- 剑指offer(30)—连续子数组的最大和
- 笔试面试算法经典--连续子数组的最大乘积及连续子数组的最大和(Java)
- 求连续子数组的最大和
- leetcode 689. Maximum Sum of 3 Non-Overlapping Subarrays 3个连续子数组最大和+动态规划DP
- 求解最大子数组问题的三种方法