小和问题(归并排序的应用)

问题描述

在一个数组中, 每一个数左边比当前数小的数累加起来, 叫做这个数组的小和。 求一个数组的小和。

样例

[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

题解

  • 对数组进行归并排序,在合并的过程中,如果左侧部分的当前元素l小于右侧部分的当前元素r,那么计算右侧部分当前位置到结束位置的元素个数,即为两部分合并之后的数组中在i右侧的元素个数;否则右侧指针下移。
  • 不会出现重复计算的情况,因为每次都是各部分之间比较,内部并不进行比较。
public static int smallSum(int[] arr) {
		if(arr==null||arr.length<2)
			return 0;
		return smallSum(arr,0,arr.length-1);
	}
	private static int smallSum(int[] arr, int i, int j) {
		if(i==j)
			return 0;
		int mid=i+(j-i)/2;
		return smallSum(arr,i,mid)+smallSum(arr,mid+1,j)+mergeSum(arr,i,j,mid);
	}
	private static int mergeSum(int[] arr, int i, int j, int mid) {
		int s=0;
		int ii=i,ij=mid+1;
		int []help=new int[j-i+1];
		int k=0;
		while(ii<=mid&&ij<=j) {
			if(arr[ii]<arr[ij]) {
				s+=(j-ij+1)*arr[ii];
				help[k++]=arr[ii++];
			}else {
				help[k++]=arr[ij++];
			}
		}
		while(ii<=mid)
			help[k++]=arr[ii++];
		while(ij<=j)
			help[k++]=arr[ij++];
		for(k=0;k<help.length;k++) {
			arr[i+k]=help[k];
		}
		return s;
	}

应用2:在一个数组中, 左边的数如果比右边的数大, 则折两个数构成一个逆序对, 请打印所有逆序对

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值