小和问题

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

比如[1,3,4,2]1左边比1小的数没有,3左边比3小的数有1,4左边比4小的数有1,3,2左边比2小的数有1.那么这个数组的小和是

1+1+3+1=6

 暴力方法是每次遍历的时候,都要再把前面的比较一下,这样时间复杂度是O(n^2)这样明显不行,仔细思考下过程,就是归并排序的过程之中,

在你进行归并的时候,你需要左边比右边小的时候记录下来,进行累加,可以算出右边有多少个数比它大,代码如下:

public static int getSmallSum(int[] a, int l, int r) {
        if (l >= r || a.length == 1)
            return 0;
        int mid = l + ((r - l) >> 1);
        //左边求小和加右边求小和加整体求整体小和
        return getSmallSum(a, l, mid) +
                getSmallSum(a, mid + 1, r) +
                process(a, l, mid, r);
    }

    private static int process(int[] a, int l, int mid, int r) {
        int[] aux = new int[r - l + 1];
        int lo = l;
        int hi = mid + 1;
        int index = 0;
        int sum = 0;
        while (lo <= mid && hi <= r) {
            if (a[lo] < a[hi]) {
                //左边只有小才能算是小和,相等不算
                sum = sum + (r - hi + 1) * a[lo];
                aux[index++] = a[lo++];
            } else {
                aux[index++] = a[hi++];
            }
        }
        while (lo <= mid) {
            aux[index++] = a[lo++];
        }
        while (hi <= r) {
            aux[index++] = a[hi++];
        }
        for (int aux1 : aux) {
            a[l++] = aux1;
        }
        return sum;
    }

 

posted @ 2020-06-12 17:22  junlancer  阅读(413)  评论(0编辑  收藏  举报