每日一题小和问题
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;
以上是关于每日一题小和问题的主要内容,如果未能解决你的问题,请参考以下文章