最小子段和

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define N 10
#define MAX_RANDOM_NUM  20

/**
 * 求最大子段和
 *      情况1:左子段长
 *      情况2:右子段长
 *      情况3:右子段一部分和左子段一部分相连长
 * @param arr        数组
 * @param left       左下标
 * @param right      右下标
 * @return
 */
int maxSubNum(int *arr, int left, int right) {
    int sum = 0;
    if (left == right) {
        sum = arr[left];
    } else {
        //获取左右子段的最大和
        int center = (left + right) >> 1;
        int leftSum = maxSubNum(arr, left, center);
        int rightSum = maxSubNum(arr, center + 1, right);
        //获取情况3的长度
        //左子段 从右到左最大的和
        int s1 = 0;
        int tmpLeftSum = 0;
        for (int i = center; i >= left; i--) {
            tmpLeftSum += arr[i];
            if (tmpLeftSum > s1) {
                s1 = tmpLeftSum;
            }
        }
        //右子段  从左到右最大的和
        int s2 = 0;
        int tmpRightSum = 0;
        for (int i = center + 1; i <= right; i++) {
            tmpRightSum += arr[i];
            if (tmpRightSum > s2) {
                s2 = tmpRightSum;
            }
        }
        //情况3将两段相加获取情况3的和
        sum = s1 + s2;

        //判断3种情况 获取最大和
        if (sum < leftSum) {
            sum = leftSum;
        }
        if (sum < rightSum) {
            sum = rightSum;
        }
    }
    return sum;
}

//给数组进行赋值
void random(int *arr) {
    //设置随机数种子
    srand((unsigned int) time(NULL));
    printf("生成的随机数组: ");
    for(int i = 0; i < N; i++){
        int num = (rand() % (MAX_RANDOM_NUM)) + 1;
        //随机正负号
        if (rand() % 2) {
            //负数
            num = -num;
        }
        //赋值
        printf(" %d ", num);
        arr[i] = num;
    }
    printf("\n");
}

int main() {
    int *arr = (int *) malloc(N * sizeof(int));
    random(arr);
    printf("最大子段和: %d",maxSubNum(arr,0, N - 1));
    return 0;
}
posted @ 2024-05-15 16:26  ._Liu  阅读(42)  评论(0)    收藏  举报