算法导论4-1笔记

找出数组中的最大和子序列


方法:

(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


猜你喜欢

转载自blog.csdn.net/sscout/article/details/80984832
4-1