题目分析

根据左神讲的smallSum
先可以写出暴力方法:

数组 s = [1, 3, 5, 2, 4, 6] ,在 s[0] 的左边小于或等于 s[0] 的数的和为 0 ; 在 s[1] 的左边小于或等于 s[1] 的数的和为 1 ;在 s[2] 的左边小于或等于 s[2] 的数的和为 1+3=4 ;在 s[3] 的左边小于或等于 s[3] 的数的和为 1 ;

public static int comparator(int[] arr) {
        if(arr == null || arr.length < 2) {
            return 0;
        }
        int res = 0;
        for (int i = 1; i < arr.length; i++) {
            for (int j = 0; j < i; j++) {
                res += arr[j] <= arr[i] ? arr[j] : 0; // 小于或等于
            }
        }
        return res;
    }

暴力的解法是当前位置向左看,把所有小于等于它的数加到结果里去;反过来想,一个数字要被加几次,取决于后面有多少大于或等于它的数。例如s = [1, 3, 5, 2, 4, 6] 对于3来说,5,4,6 向左看时会导致res += 3

归并排序使子序列有序,再将子序列合并得到完整有序表的过程,可以方便地顺便去计算小和。若左边p1指向的值小于右侧p2指向的值,我们可以根据下标计算,快速得出右侧有(r - p2 + 1)大于或等于p1位置数值的数,利用归并排序的稳定性,我们可以不重复无遗漏地计算出小和。

代码实现

import java.util.*;

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param nums int整型ArrayList 
     * @return long长整型
     */
    public long calArray (ArrayList<Integer> nums) {
        if(nums == null || nums.size() < 2) {
            return 0;
        }
        Integer[] arr = new Integer[nums.size()];
        nums.toArray(arr);
        return mergeSort(arr, 0, nums.size() - 1);
    }
    public long mergeSort(Integer[] arr, int l, int r) {
        if(l >= r) {
            return 0;
        }
        int mid = l + ((r - l) >> 1);
        return mergeSort(arr, l, mid) +
            mergeSort(arr, mid + 1, r) +
            merge(arr, l , mid, r);
    }
    public long merge(Integer[] arr, int l, int m, int r) {
        Integer[] help = new Integer[r - l + 1];
        long res = 0l;
        int i = 0;
        int p1 = l;
        int p2 = m + 1;
        while(p1 <= m && p2 <= r) {
            res += arr[p1] <= arr[p2] ? arr[p1] * (r - p2 + 1) : 0;
            help[i++] = arr[p1] <= arr[p2] ? arr[p1++] : arr[p2++];
        }
        while(p1 <= m) {
            help[i++] = arr[p1++];
        }
        while(p2 <= r) {
            help[i++] = arr[p2++];
        }
        for(i = 0; i < help.length; ++i) {
            arr[l + i] = help[i];
        }
        return res;
    }
}