49. 计算右侧小于当前元素的个数
题目描述
给定一个整数数组 nums,按要求返回一个新数组 counts。数组 counts 中该位置的值表示在 nums[i] 右边且比它小的元素的数量。

题目示例
输入: [5, 2, 6, 1]
输出: [2, 1, 1, 0]
解释:
- 5 的右边有 2 个比它小的数 (2, 1)
- 2 的右边有 1 个比它小的数 (1)
- 6 的右边有 1 个比它小的数 (1)
- 1 的右边没有比它小的数

解题思路
这道题的核心逻辑其实和'求逆序对'非常接近,但输出形式变了。我们不需要统计总数,而是要为每个元素记录右侧比它小的数量。
归并排序的一个特性是:在合并两个有序子数组时,如果左边的元素大于右边的元素,那么左边这个元素就构成了若干个逆序对。利用这一点,我们可以边排序边计数。
不过有个坑:归并排序会打乱原数组顺序,下标自然也会变动。为了知道结果对应的是哪个原始元素,我们需要绑定原始下标。也就是维护一个索引数组,让元素和它的初始位置始终在一起移动。
C++ 实现
class Solution {
public:
vector<int> counts;
vector<int> index; // 记录 nums 中当前元素的原始下标
vector<int> tmp;
vector<int> tmpi; // 临时记录合并后对应元素位置变化下标随之变化的数组
vector<int> countSmaller(vector<int>& nums) {
int n = nums.size();
if (n == 0) {};
counts.(n);
index.(n);
tmp.(n);
tmpi.(n);
( i = ; i < n; i++) {
index[i] = i;
}
(nums, , n - );
counts;
}
{
(left >= right) ;
mid = (right - left) / + left;
(nums, left, mid);
(nums, mid + , right);
cur1 = left, cur2 = mid + , i = ;
(cur1 <= mid && cur2 <= right) {
(nums[cur1] > nums[cur2]) {
counts[index[cur1]] += right - cur2 + ;
tmpi[i] = index[cur1];
tmp[i++] = nums[cur1++];
} {
tmpi[i] = index[cur2];
tmp[i++] = nums[cur2++];
}
}
(cur1 <= mid) {
tmpi[i] = index[cur1];
tmp[i++] = nums[cur1++];
}
(cur2 <= right) {
tmpi[i] = index[cur2];
tmp[i++] = nums[cur2++];
}
( j = left; j <= right; j++) {
nums[j] = tmp[j - left];
index[j] = tmpi[j - left];
}
}
};






