您的位置:首页 > 其它

【算法】小和问题

2019-04-12 10:10 106 查看
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hello_ape/article/details/89226312

问题描述:在一个数组中,每一个元素左边比当前元素值小的元素值累加起来,叫做这个数组的小和
例如:[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

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

[code]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;
}

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: