题目:315
题意:
给定一个整数数组 nums,按要求返回一个新数组 counts。数组 counts 有该性质: counts[i] 的值是 nums[i] 右侧小于 nums[i] 的元素的数量。
题解:归并排序采用求逆序对的方式计数
参考:参考资料
代码:
class Solution {
private:
vector<int> cnt;
int* temp; //临时数组
int* index; //索引数组
int n;
public:
vector<int> countSmaller(vector<int>& nums) {
n = nums.size();
if (n == 0)return cnt;
cnt = vector<int>(n, 0);
temp = new int[n];
index = new int[n];
for (int i = 0; i < n; ++i)
index[i] = i;
merge(nums, 0, n - 1);
return cnt;
}
void merge(vector<int>& nums, int l, int r) { //归并排序
if (l == r)return;
int mid = (l + r) >> 1;
merge(nums, l, mid);
merge(nums, mid + 1, r);
//归并优化
if (nums[index[mid]] > nums[index[mid + 1]])
mergeOfSortedArrAndCount(nums, l, mid, r);
}
void mergeOfSortedArrAndCount(vector<int>& nums, int l, int mid, int r) {//归并并进行计数
for (int i = l; i <= r; ++i) {
temp[i] = index[i];
}
int i = l;
int j = mid + 1;
for (int k = l; k <= r; ++k) {
if (i > mid)
index[k] = temp[j++];
else if (j > r) {
index[k] = temp[i++];
cnt[index[k]] += (r - mid);
}
else if (nums[temp[i]] <= nums[temp[j]]) { //此处注意一下,如果写成小于,就会将等于的数也计算在内
index[k] = temp[i++];
cnt[index[k]] += (j - mid - 1);
}
else {
index[k] = temp[j++];
}
}
}
};