赞
踩
在一个数组中,每一个数左边比当前数小的数累加起来,叫做这个数组的小和。求一个数组的小和。
例子:
[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小的数 => 1右边有几个比1大的数(4个)1 * 4
3左边比3小的数 => 3右边有几个比3大的数(2个)3 * 2
4左边比4小的数 => 4右边有几个比4大的数(1个)4 * 1
2左边比2小的数 => 2右边有几个比2大的数(1个)2 * 1
5左边比5小的数 => 5右边有几个比5大的数(没有)
所以小和为 1 * 4 + 3 * 2 + 4 * 1 + 2 * 1 = 16
在归并排序的基础上,加上一行代码即可求解此题
sum += nums[p1] * (right - p2 + 1);
还有一点不一样的就是排序的时候,左右相等的情况下,要先放右边的数。
在每一次归并操作比较元素大小的时候,加一步求和操作
int small_sum(vector<int>& nums, int left, int mid, int right) { vector<int> num; int p1 = left; int p2 = mid + 1; int sum = 0; while (p1 <= mid && p2 <= right) { if (nums[p1] < nums[p2]) { sum += nums[p1] * (right - p2 + 1); num.push_back(nums[p1++]); } else { num.push_back(nums[p2++]); } } while (p1 <= mid) { num.push_back(nums[p1++]); } while (p2 <= right) { num.push_back(nums[p2++]); } for (int i = 0; i < num.size(); i++) { nums[left + i] = num[i]; } return sum; } int small_sum_merge_sort(vector<int>& nums, int left, int right) { if (left == right) { return 0; } int mid = left + ((right - left) >> 1); // small_sum_merge_sort(nums, left, mid); // small_sum_merge_sort(nums, mid + 1, right); // small_sum(nums, left, mid, right); return small_sum_merge_sort(nums, left, mid) + small_sum_merge_sort(nums, mid + 1, right) + small_sum( nums, left, mid, right); }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。