找出数组中的最大和子序列
方法:
(1)首先找出数组的中间数字
(2)由中间数字向左侧的数字逐个相加,并记录比较上一次和的大小,如果和增大,就记录它的索引
然后同样方法向右侧,但是是从中间数字的右边一个数字向右侧的数字逐个相加
(3)将两边所记录索引之间的数字即为最大和子序列
(4)利用这种方法递归实现,将数组拆分为小数组,然后比较左右两侧的和的大小和两侧相加的大小
Java代码实现
找出数组的最大和值的子序列
public static int[] findMaxCrossingSubarray(int[] arr,int low,int mid,int high){ // low是最小的数组索引下标,high是最大的数组索引下标
int sum = 0;
int leftSum = 0;
int maxLeftIndex = 0;
for (int i = mid;i >= low;i--){
sum += arr[i];
if(sum > leftSum){
leftSum = sum;
maxLeftIndex = i;
}
}
int rightSum = 0;
sum = 0;
int maxRightIndex = 0;
for(int j = mid +1;j <= high;j++){
sum += arr[j];
if(sum > rightSum){
rightSum = sum;
maxRightIndex = j;
}
}
return new int[] {maxLeftIndex,maxRightIndex,leftSum+rightSum};
}
上述方法是存在bug的,当一侧出现负数最大和时,相加的和值是减小的。
然后递归调用下面方法,将原始数组递归拆分为长度小数组然后比较左侧数组的最大和,右侧数组的最大和,以及通过上述方法实现的两侧数组最大和值,最后得出真正的数组的子序列最大和值与最大和值子序列的位置
public static int[] findMaximumSubarray(int[] arr,int low,int high){
if(high == low){ //判断该数组是否只有一个元素
return new int[]{low,high,arr[low]};
}else{
int mid = (low + high)/2;
int[] leftMaxArr = findMaximumSubarray(Arrays.copyOfRange(arr,0,mid+1),0,mid);
int[] rightMaxArr = findMaximumSubarray(Arrays.copyOfRange(arr,mid+1,high+1),0,arr.length-mid-2);
int[] crossMaxArr = findMaxCrossingSubarray(arr,low,mid,high);
if(leftMaxArr[2] >= rightMaxArr[2] && leftMaxArr[2] >= crossMaxArr[2]){
return leftMaxArr;
}else if(rightMaxArr[2] >= leftMaxArr[2] && rightMaxArr[2] >= crossMaxArr[2]){
return rightMaxArr;
}else{
return crossMaxArr;
}
}
}
语文不好。。表达的不清楚!!
2018/7/10