每日一题小和问题

Posted 唐宋xy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了每日一题小和问题相关的知识,希望对你有一定的参考价值。

题目

给定一个可能有序也可以有序的数组,计算这个数组的小和

小和:数组中,每个数组左边比当前数小的数累加起来就是小和

例如:

arr = 1,3,2,5,9,10,6

res = 50

解析

解这道题,直接想到的肯定是暴力法,直接双重for循环,计算每个元素左边的元素的大小,然后加和即可。但是如果要更好的时间复杂度,就不能使用暴力法。

这道题思路是要拿到每个元素的左边的元素并比较大小,这样看的话,和排序其实有点像,并且如果使用归并排序,那么可以拿到每个元素的左边所有元素。

**思路:**利用归并排序的思想,对数组进行排序,在排序的过程中,可以拿到每个元素左边的元素,那么对小于当前的元素计算小和即可

因为归并排序时先将数组划分为最小的单位,然后再进行比较大小并合并,那么在合并的过程中,就可以拿到当前元素左边的数是哪些,并且需要比较大小的,那么使用一个额外变量计算合并过程中的小和就可以

代码实现

public static int smallSum(int[] arr) 
    if(arr == null || arr.length == 0) 
        return 0;
    
    return process(arr, 0, arr.length - 1);


private static int process(int[] arr, int L, int R) 
    if(L >= R) 
        return 0;
    
    int mid = L + ((R - L) >> 1);
    return process(arr, L, mid) + process(arr, mid + 1, R) + merge(arr, L, mid, R);


private static int merge(int[] arr, int L, int mid, int R) 
    int[] help = new int[R - L + 1];
    int p1 = L;
    int p2 = mid + 1;
    int sum = 0;
    int index = 0;
    while (p1 <= mid && p2 <= R) 
        sum += arr[p1] < arr[p2] ? (R - p2 + 1) * arr[p1] : 0;
        // 这里需要注意,只能小于,不能小于等于,因为等于的情况下,需要先将右边数组的值放入help数组中,然后移动p2指针
        // 这样才能知道右边数组中有多少个数比当前的p1指向的数大
        help[index++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
    
    while(p1 <= mid) 
        help[index++] = arr[p1++];
    
    while(p2 <= R) 
        help[index++] = arr[p2++];
    

    for (int i = 0; i < help.length; i++) 
        arr[L + i] = help[i];
    

    return sum;

以上是关于每日一题小和问题的主要内容,如果未能解决你的问题,请参考以下文章

每日一题小和问题

每日一题逆序对

每日一题逆序对

每日一题逆序对

PMP每日一题

Leetcode每日一题(3)