前缀和简单题

发布时间 2024-01-03 14:08:08作者: Sprinining

前缀和简单题

2574. 左右元素和的差值

int *leftRightDifference(int *nums, int numsSize, int *returnSize) {
    int *res = (int *) malloc(sizeof(int) * numsSize);
    *returnSize = numsSize;
    int leftSum = 0, rightSum = 0;
    // 求和
    for (int i = 0; i < numsSize; ++i) rightSum += nums[i];
    for (int i = 0; i < numsSize; ++i) {
        // 计算后缀和
        rightSum -= nums[i];
        res[i] = abs(leftSum - rightSum);
        // 计算下次用的前缀和
        leftSum += nums[i];
    }
    return res;
}

1588. 所有奇数长度子数组的和

int sumOddLengthSubarrays(int *arr, int arrSize) {
    int res = 0;
    int *sum = (int *) calloc(arrSize + 1, sizeof(int));
    for (int i = 1; i <= arrSize; ++i)
        sum[i] += sum[i - 1] + arr[i - 1];
    int gap = 1;
    // i = 0, sum[i+gap] - sum[i] gap=1
    // i = 0, sum[i+gap] - sum[i] gap=3
    // i = 0, sum[i+gap] - sum[i] gap=5
    while (gap <= arrSize) {
        for (int i = gap; i <= arrSize; ++i) {
            res += sum[i] - sum[i - gap];
        }
        gap += 2;
    }
    return res;
}
// todo
int sumOddLengthSubarrays(int *arr, int arrSize) {
    int res = 0;
    for (int i = 0; i < arrSize; ++i) {
        int left = i + 1, right = arrSize - i;
        int leftEven = (left + 1) >> 1, rightEven = (right + 1) >> 1;
        int leftOdd = left >> 1, rightOdd = right >> 1;
        res += (leftEven * rightEven + leftOdd * rightOdd) * arr[i];
    }
    return res;
}

1732. 找到最高海拔

int largestAltitude(int *gain, int gainSize) {
    int sum = 0;
    int max = 0;
    for (int i = 0; i < gainSize; ++i) {
        sum += gain[i];
        if (max < sum) max = sum;
    }
    return max;
}

2485. 找出中枢整数

int pivotInteger(int n) {
    int total = (1 + n) * n >> 1;
    int prefixSum = total;
    // 倒着找的更快
    for (int i = n; i >= 1; i--) {
        // 检查前i个数之和是否等于后(n-i+1)个数之和
        if (prefixSum == ((i + n) * (n - i + 1) >> 1)) return i;
        prefixSum -= i;
    }
    return -1;
}
// 数学计算
int pivotInteger(int n) {
    int total = n * (n + 1) / 2;
    int x = sqrt(total);
    return x * x == total ? x : -1;
}
// 打表
int pivotInteger(int n) {
    switch (n) {
        case 1:
            return 1;
        case 8:
            return 6;
        case 49:
            return 35;
        case 288:
            return 204;
        default:
            return -1;
    }
}

303. 区域和检索 - 数组不可变

typedef struct {
    int *sum;
} NumArray;


NumArray *numArrayCreate(int *nums, int numsSize) {
    NumArray *numArray = (NumArray *) malloc(sizeof(NumArray));
    numArray->sum = (int *) calloc(numsSize + 1, sizeof(int));
    // 计算前缀和
    for (int i = 1; i <= numsSize; ++i) {
        numArray->sum[i] += numArray->sum[i - 1] + nums[i - 1];
    }
    return numArray;
}

int numArraySumRange(NumArray *obj, int left, int right) {
    return obj->sum[right + 1] - obj->sum[left];
}

void numArrayFree(NumArray *obj) {
    if (obj != NULL) {
        free(obj);
        obj = NULL;
    }
}

1480. 一维数组的动态和

int *runningSum(int *nums, int numsSize, int *returnSize) {
    int *res = (int *) calloc(numsSize, sizeof(int));
    *returnSize = numsSize;
    res[0] = nums[0];
    for (int i = 1; i < numsSize; ++i)
        res[i] += res[i - 1] + nums[i];
    return res;
}

2848. 与车相交的点

// todo

1413. 逐步求和得到正数的最小值

int minStartValue(int *nums, int numsSize) {
    int prefixSum = 0;
    int min = 101;
    for (int i = 0; i < numsSize; ++i) {
        prefixSum += nums[i];
        if (prefixSum < min) min = prefixSum;
    }
    if (min > 0) return 1;
    return 1 - min;
}

LCR 012. 寻找数组的中心下标

int pivotIndex(int *nums, int numsSize) {
    int total = 0;
    for (int i = 0; i < numsSize; ++i)
        total += nums[i];

    int prefixSum = 0;
    for (int i = 0; i < numsSize; ++i) {
        if (prefixSum == total - prefixSum - nums[i])
            return i;
        prefixSum += nums[i];
    }
    return -1;
}

1893. 检查是否区域内所有整数都被覆盖

// todo