赞
踩
在一个数组中,每一个数左边比当前数小的数累加起来,叫做这个数组的小和。求一个数组的小和。
例:求数组[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
* 利用归并排序的思想可以降低时间复杂度
* 求小和的逆向思维,举例来说:小和的算法等价于找出1右边比1大的数的个数是4,则整个数组的小和增加1*4;3的右边有2个数比3大,则整个数组的小和增加3*2;4的右边比4大的有1个数,则整个数的小和增加4*1;2的右边比2大的数有1个,则小和增加2*1,5的右边没有比5大的数。
* 求一个数的右边有多少个数比它大,就可以用归并排序的思路来完成
* 采用递归的方式,在归并的过程中,一边排序,一边计算小和
- public static int smallSum(int[] arr){
- //数组长度小于2时,小和为0
- if(arr == null || arr.length < 2){
- 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 sum = 0; //用于累加小和
- int mid = L + ((R - L) >> 1); //中间位置
- sum += process(arr, L, mid); //累加左侧排序求小和的结果
- sum += process(arr, mid+1, R); //累加右侧排序求小和的结果
- sum += merge(arr, L, mid, R); //累加归并左右两部分时产生小和的结果
- return sum;
- }
-
- /**
- * 关键:既要排序,又要求小和,
- * 并且当左组与右组的元素值相等时,一定要先拷贝右组的值(即让右指针先移动),这也是与标准的mergeSort的区别
- * 这样才能确定产生的小和个数。
- * 为什么需要排序:因为在合并的过程中排序后,在下一次合并计算小和的时候更加方便,且不会遗漏重复。
- */
- private static int merge(int[] arr, int L, int mid, int R) {
- int sum = 0; //用于累加小和
- int help[] = new int[R - L + 1];
- int p1 = L;
- int p2 = mid+1;
- int i = 0; //help的下标指针
- while(p1<=mid && p2 <=R){ //当两个下标都没有越界
- /*if(arr[p1] < arr[p2]){ //当左边部分的数小于右边部分的数时,产生小和arr[p1] * (R-p2+1)
- help[i++] = arr[p1];
- sum += arr[p1] * (R - p2 + 1);
- p1++; //左指针右移
- }else{//如果右组的数小于等于左组的数,则不产生小和,只是复制该值,并将右指针右移
- help[i++] = arr[p2++];
- }*/
-
- //以上的代码的优化
- sum += arr[p1] < arr[p2] ? arr[p1] * (R - p2 + 1) : 0;
- help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
-
- }
- //以下两个情况,至多存在一种
- while(p1 <= mid){
- help[i++] = arr[p1++];
- }
- while(p2 <= R){
- help[i++] = arr[p2++];
- }
-
- for(int j=0; j<help.length; j++){
- arr[L+j] = help[j];
- }
- return sum;
- }
-
- public static void main(String[] args) {
- int[] arr = {3,3,2,6,1,9,4,7,11,8,10,5};
- System.out.println(smallSum(arr));
- for(int num : arr){
- System.out.print(num + " ");
- }
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。