【算法】小和问题

问题描述:在一个数组中,每一个元素左边比当前元素值小的元素值累加起来,叫做这个数组的小和
例如:[2,3,4,1,5]
2左边比2小的元素:无
3左边比3小的元素:2
4左边比4小的元素:2,3
1左边比1小的元素:无
5左边比5小的元素:2,3,4,1
小和small_sum = 2 + 2 + 3 + 2 + 3 + 4 + 1 = 17

可以使用归并排序思想,来解决小和问题

int 
small_sum(int a[], int n)                       
{
	if (a == NULL || n < 2)
		return 0;
	return small_sum(a, 0, n - 1);
}

int
small_sum(int a[], int left, int right)
{
	if (a == NULL || (right - left+1) < 2)
		return 0;
	//获取数组的中间位置
	int mid = left + ((right - left) >> 1);
	/*小和问题 可以采用分治的思想
	  1、将数组划分为两部分
	  2、求左边一部分的小和
	  3、求右边一部分的小和
	  4、合并左边和右边,求左边部分在右边里的小和
	  5、将2、3、4部分求和,即为原数组的小和
	*/
	return small_sum(a, left, mid) + small_sum(a, mid + 1, right) + merge_small_sum(a, left, mid, right);

}

int
merge_small_sum(int a[], int left, int mid, int right)
{
	//获取数组长度
	int len = right - left + 1;
	//分配地址空间
	int *temparry = (int *)malloc(sizeof(int)*len);
	//保存小和,初始值为0
	int smallsum = 0;
	//左边数组的起始位置
	int pos1 = left;
	//右边数组的起始位置
	int pos2 = mid + 1;
	//辅助数组的当前位置
	int pos3 = 0;
	//如果左边数组或者右边数组没有越界
	while (pos1 <= mid && pos2 <= right){
		//计算小和,如果左边数值比右边数值小,则产生小和
		smallsum += a[pos1] < a[pos2] ? (right - pos2 + 1)*a[pos1] : 0;
		//将最小值放入辅助数组下一个空闲位置
		temparry[pos3++] = a[pos1] < a[pos2] ? a[pos1++] : a[pos2++];
	}
	//拷贝剩余部分
	while (pos1 <= mid){
		temparry[pos3++] = a[pos1++];
	}
	while (pos2 <= right){
		temparry[pos3++] = a[pos2++];
	}
	//将辅助数组赋值给原数组
	for (int i = 0; i < len; ++i)
		a[i + left] = temparry[i];
	//释放内存
	delete  temparry;
	//返回当前小和
	return smallsum;
}




 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值