算法题 - 小和问题

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

描述

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

例子

[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

解题思路

如果直接用两层for循环扫,时间复杂度是O(n^2),但是可以通过归并排序的方法将时间复杂度降到O(nlogn)

答案

/**
 * Small Sum Question
 */
public class LeetCodeTest07 {

    private static Integer[] assist;

    private static int result = 0;

    public static void main(String[] args) {
        Integer[] arr = {1, 3, 4, 2, 5};
        sort(arr);
        System.out.println("Result: " + result);
    }

    public static void sort(Integer[] a) {
        assist = new Integer[a.length];
        int lo = 0;
        int hi = a.length - 1;
        sort(a, lo, hi);
    }

    public static void sort(Integer[] a, int lo, int hi) {
        if (hi <= lo) {
            return;
        }
        int mid = lo + (hi - lo) / 2;
        sort(a, lo, mid);
        sort(a, mid + 1, hi);

        merge(a, lo, mid, hi);
    }

    public static void merge(Integer[] a, int lo, int mid, int hi) {
        int i = lo;
        int p1 = lo;
        int p2 = mid + 1;
        while (p1 <= mid && p2 <= hi) {
            if (less(a[p1], a[p2])) {
                result += (hi - p2 + 1) * a[p1];
                assist[i++] = a[p1++];
            } else {
                assist[i++] = a[p2++];
            }
        }
        while (p1 <= mid) {
            assist[i++] = a[p1++];
        }
        while (p2 <= hi) {
            assist[i++] = a[p2++];
        }
        if (hi + 1 - lo >= 0) System.arraycopy(assist, lo, a, lo, hi + 1 - lo);
    }

    private static boolean less(Integer i, Integer j) {
        return i.compareTo(j) < 0;
    }
}

posted @ 2021-07-10 11:06  灰色飘零  阅读(155)  评论(0)    收藏  举报