小数和问题

161 阅读1分钟

题目描述

在一个数组中,每一个数左边比当前数小的数累加起来,叫做这个数组的小和。求一个数组的小和。

例子:
[1,3,4,2,5] 1左边比1小的数,没有;3左边比3小的数,1;4左边比4小的数,1、3;2左边比2小的数,1;5左边比5小的数,1、3、4、2;所以小和为1+1+3+1+1+3+4+2=16

实现

#include <stdio.h>

int Merge(int *nums, int left, int mid, int right)
{
    int help[right-left+1];
    int p1 = left;
    int p2 = mid + 1;
    int i = 0;
    int res = 0;
    while (p1 <= mid && p2 <= right) {
        res += nums[p1] < nums[p2] ? (right - p2 + 1) * nums[p1] : 0;
        help[i++] = nums[p1] < nums[p2] ? nums[p1++] : nums[p2++];
    }
    while (p1 <= mid) {
        help[i++] = nums[p1++];
    }
    while (p2 <= right) {
        help[i++] = nums[p2++];
    }
    for (i = 0; i < right - left + 1; i++) {
        nums[left+i] = help[i];
    }
    return res;
}

int Process(int *nums, int left, int right)
{
    if (left == right) {
        return 0;
    }
    int mid = left + ((right - left) >> 1);
    return Process(nums, left, mid) + Process(nums, mid + 1, right) + Merge(nums, left, mid, right);
}

int SmallSum(int *nums, int len)
{
    if (nums == NULL || len <= 1) {
        return 0;
    }
    return Process(nums, 0, len - 1);
}

int main()
{
    int nums[10] = {12, 34, 15, 2, 5, 14, 16, 10, 9, 1};
    printf("Before sort: ");
    for (int i = 0; i < 10; i++) {
        printf(" %d", nums[i]);
    }
    printf("\n");

    printf("%d\n", SmallSum(nums, 10));

    printf("After  sort: ");
    for (int i = 0; i < 10; i++) {
        printf(" %d", nums[i]);
    }
    printf("\n");  
    return 0;
}