归并排序实战:计算右侧小于当前元素个数与翻转对
49. 计算右侧小于当前元素的个数
题目描述
给定一个整数数组 nums,按要求返回一个新数组 counts。其中 counts[i] 表示在 nums[i] 右边且比它小的元素个数。

解法思路
这道题本质上是求逆序对的变种。普通的逆序对统计的是总数,而这里需要记录每个元素对应的数量。
归并排序过程中,元素的下标会发生变化,为了准确统计,我们需要维护一个辅助数组来绑定原始下标。当左半区间的元素大于右半区间的元素时,说明左边的这个元素比右边剩余的所有元素都大,此时可以直接累加计数。
C++ 代码实现
class Solution {
public:
vector<int> counts;
vector<int> index; // 记录 nums 中当前元素的原始下标
vector<int> tmp;
vector<int> tmpi; // 临时记录合并后对应元素位置变化下标随之变化的数组
vector<int> countSmaller(vector<int>& nums) {
counts.resize(nums.size());
index.resize(nums.size());
tmp.resize(nums.size());
tmpi.resize(nums.size());
// 初始化 index,使得 nums 每个元素下标和 index 一一对应
for(int i = 0; i < nums.size(); i++) {
index[i] = i;
}
mergesort(nums, 0, nums.size() - 1);
return 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];
}
}
};





