在一个数组中,每一个数左边比当前数小的数累加起来,叫做这个数组的小和。求一个数组的小和?
例子:[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
思路分析
第一种思路
暴力递归
- 通过一个指针,然后遍历去看左边有多少个数比他小,然后进行相加,最终的得到结果
第二种思路
通过归并排序在进行排序的同时拿到他的小和
- 可以转换思路,题目的要求是要找到左边数比该数小的数字将加,那么我们可以转变为看看右边有多少个数字比他大(假设为n),表示该数在小和的计算中出现了n次,最后相加即可
- 即右边比1大的数有4个,比3大的数有2个,比4大的数有1个,比2大的数有1个。小和为:
1×4+3×2+4×1+2×1=16
流程图
java
相关代码:归并排序
public static void main(String[] args) {
// 定义一个整型数组
int[] arr = {1, 3, 4, 2, 5};
// 调用 smallSum 方法并打印结果
System.out.println(smallSum(arr));
}
/**
* 计算数组中小和的方法
* @param arr 整型数组
* @return 返回小和的结果
*/
public static int smallSum(int[] arr) {
// 如果数组为空或长度小于2,返回0
if (arr == null || arr.length < 2) return 0;
// 调用 process 方法并返回结果
return process(arr, 0, arr.length - 1);
}
/**
* 分治算法的核心方法,计算数组中小和的过程
* @param arr 整型数组
* @param L 数组的左边界
* @param R 数组的右边界
* @return 返回小和的结果
*/
public static int process(int[] arr, int L, int R) {
// 如果左右边界相等,返回0
if (L == R) return 0;
// 计算中间位置
int mid = L + ((R - L) >> 1);
// 递归计算左半部分的小和
int leftSum = process(arr, L, mid);
// 递归计算右半部分的小和
int rightSum = process(arr, mid + 1, R);
// 计算合并后的小和
int mergeSum = merge(arr, L, mid, R);
// 返回三部分小和的总和
return leftSum + rightSum + mergeSum;
}
/**
* 合并两个有序数组并计算小和的方法
* @param arr 整型数组
* @param L 数组的左边界
* @param M 数组的中间位置
* @param R 数组的右边界
* @return 返回小和的结果
*/
public static int merge(int[] arr, int L, int M, int R) {
// 创建一个临时数组用于存放合并后的结果
int[] help = new int[R - L + 1];
int i = 0;
// 定义两个指针分别指向左右两个有序数组的起始位置
int p1 = L;
int p2 = M + 1;
int res = 0;
// 循环比较左右部分
while (p1 <= M && p2 <= R) {
// 左半部分比右半部分小 产生小和
// (R - p2 + 1) 判断右半部分有多少个比 arr[p1] 大的数,个数乘以 arr[p1] 得到小和
res += arr[p1] < arr[p2] ? (R - p2 + 1) * arr[p1] : 0;
// 进行排序 如果左半部分当前下标值小,就将值放入临时数组然后下标+1,否则右半部分下标+1
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;
}
文档信息
- 本文作者:carpe
- 本文链接:https://carpedx.com/wiki/algorithm-small-sum/
- 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)