最大子序列和详解

最大子序列和详解

在求解最大子序列和时可以使用多种不同的方法 其中对于分治思想:将一个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 _inout

int 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;
        }
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值