最大子序列和详解

来源:互联网 发布:农村淘宝的现状分析 编辑:程序博客网 时间:2024/06/05 11:46
最大子序列和详解

在求解最大子序列和时可以使用多种不同的方法 其中对于分治思想:将一个n规模的问题分为2个n/2规模的问题,再将问题的解做简单合并。其中n/2规模的问题可以继续分开处理。对于最大子序列和最大值存在3种情况1在左边2在右边3跨越中间,如果跨越中间将左侧最左部分一直相加到右侧最右部分即可判断。
详细代码如下:

void test(){    //    int array[] = {4 , -3, 5, 2, -1, 2, 8, -2, 100};    int array[] = {-4 , -3, 5, 2, -1, 2, 8, -2, -100};    //    int array[] = {-4 , -3, 5, 2, -1, 2, 8, -2, -100, 3};    //    int array[] = {-4 , -3, 5, 2, -1, 2, 8, -2, -100, 300};    //    int array[] = {-1, 2, 3, -3};    //    int array[] = {-1, 2};    findSequence(array, sizeof(array)/sizeof(int));    findSequenceOptimize(array, sizeof(array)/sizeof(int));    findSequencePosition(array, sizeof(array)/sizeof(int));    findSequencePositionOptimize(array, sizeof(array)/sizeof(int));    int result = deleaveSequenceSum(array, sizeof(array)/sizeof(int));    NSLog(@"the result is %d", result);    int a = 0;    int b = 0;    result = deleaveSequenceSumRecursionByjeffasd(array, sizeof(array)/sizeof(int), &a, &b);    NSLog(@"the result is %d", result);}void findSequence(int arr[], int length){    static int calculateCount = 0;    int maxSum = 0;    for (int i = 0; i < length; i++) {        int sequeueSum = arr[i];        for (int j = i + 1; j < length; j++) {            sequeueSum += arr[j];            if (sequeueSum > maxSum) {                maxSum = sequeueSum;            }            printf("calculate count is %d\n", calculateCount++);        }    }    printf("maxSum is %d\n", maxSum);}/** 最优算法 */void findSequenceOptimize(int arr[], int length){    int maxSum = 0;    int sequeueSum = 0;    for (int i = 0; i < length; i++) {        sequeueSum += arr[i];        if (sequeueSum > maxSum) {            maxSum = sequeueSum;        }else if (sequeueSum < 0){            sequeueSum = 0;//重点是这个 当序列和小于0时将序列和置为0        }    }    printf("maxSum is %d", maxSum);}/** 最大子序列和带子序列的位置计算 */void findSequencePosition(int arr[], int length){    int maxSum = 0;    int start = 0;    int end = 0;    for (int i = 0; i < length; i++) {        int sequeueSum = 0;        for (int j = i; j < length; j++) {            sequeueSum += arr[j];            if (sequeueSum > maxSum) {                maxSum = sequeueSum;                end = j;                start = i;            }        }    }    for (int i = start; i <= end; i++) {        int temp = arr[i];        printf("sequence value position %d is %d\n", i, temp);    }    printf("maxSum is %d\n", maxSum);}/** 带位置计算最优算法 */void findSequencePositionOptimize(int arr[], int length){    int maxSum = 0;    int sequeueSum = 0;    int start = 0;    int end = 0;    BOOL startIsInNext = YES;    for (int i = 0; i < length; i++) {        sequeueSum += arr[i];        if (sequeueSum > maxSum) {            maxSum = sequeueSum;            end = i;            if (startIsInNext == YES) {                start = i;                startIsInNext = NO;            }        }else if (sequeueSum < 0){            sequeueSum = 0;//重点是这个 当序列和小于0时将序列和置为0            if (i != length - 1) {                startIsInNext = YES;            }        }    }    for (int i = start; i <= end; i++) {        int temp = arr[i];        printf("sequence value position %d is %d\n", i, temp);    }    printf("maxSum is %d", maxSum);}#define  _in#define _out#define _inoutint findSequencePositionByDeleave(int arr[], int length, _out int * startP, _out int * endP){    int maxSum = 0;    //    *startP = 0;    //    *endP = 0;    for (int i = 0; i < length; i++) {        int sequeueSum = 0;        for (int j = i; j < length; j++) {            sequeueSum += arr[j];            if (sequeueSum > maxSum) {                maxSum = sequeueSum;                *endP = j;                *startP = i;            }        }    }    for (int i = *startP; i <= *endP; i++) {        int temp = arr[i];        printf("sequence value position %d is %d\n", i, temp);    }    //    //左侧    //    int mid = length/2;    //左侧 0-mid    //右侧 mid+1 - length    //1.值全部在左侧    //2.值全部在右侧    //3.值跨越左侧和右侧    printf("maxSum is %d\n", maxSum);    return maxSum;}/** 将问题分成两部分再分别处理 伪分治算法 */int deleaveSequenceSum(_in int arr[], _in int length){    //左侧    int mid = length/2;    int leftStart = 0;    int rightEnd = 0;    int leftSum = 0;    int rightSum = 0;    int tempSum = 0;    int tempLeftStart = 0;    leftSum = findSequencePositionByDeleave(arr, mid, &leftStart, &rightEnd);    rightSum = findSequencePositionByDeleave(&arr[mid], length - (mid), &tempLeftStart, &rightEnd);    rightEnd = rightEnd + mid;    for (int i = leftStart; i <= rightEnd; i++) {        tempSum += arr[i];        printf("sequence value tempSum %d is %d\n", i, tempSum);    }    int leftRightMax = leftSum > rightSum ? leftSum : rightSum;    if (tempSum > leftRightMax ) {        return tempSum;    }else{        return leftRightMax;    }}//首先找到问题的最小规模 最小规模的计算要和 非最小规模的计算分开 非最小规模可以将问题拆分成两个或更多个相同或相似的子问题,再把子问题分成更小的子问题 再将多个子问题的和做合并//分治递归解决问题int deleaveSequenceSumRecursionByjeffasd(_in int arr[], _in int length, _out int * startP, _out int * endP){    //问题的最小规模 - 当length为2时还可以再次细分    static int calculateCount = 0;    printf("calculate count is %d\n", calculateCount++);    if (length <= 1) {        //起点和重点都是 0        *startP = 0;        *endP = 0;        return arr[0];    }else{        //左侧        int mid = length/2;        int leftStart = 0;        int rightEnd = 0;        int leftStartTemp = 0;        int rightEndTemp = 0;        int leftSum = 0;        int rightSum = 0;        int tempSum = 0;        leftSum = deleaveSequenceSumRecursionByjeffasd(arr, mid, &leftStart, &rightEndTemp);//计算左侧 起点 此处不关心 右侧结束点        rightSum = deleaveSequenceSumRecursionByjeffasd(&arr[mid], length - (mid), &leftStartTemp, &rightEnd);//计算右侧 结束点 此处不关心 左侧起点        leftStartTemp = leftStartTemp + mid;        rightEnd = rightEnd + mid;        for (int i = leftStart; i <= rightEnd; i++) {            tempSum += arr[i];            printf("sequence value tempSum %d is %d\n", i, tempSum);        }        int leftRightMax = leftSum > rightSum ? leftSum : rightSum;        if (tempSum > leftRightMax ) {            *startP = leftStart;            *endP = rightEnd;            return tempSum;        }else{            if (leftSum > rightSum) {                *startP = leftStart;                *endP = rightEndTemp;            }else{                *startP = leftStartTemp;                *endP = rightEnd;            }            return leftRightMax;        }    }}