0%

315. 计算右侧小于当前元素的个数

315. 计算右侧小于当前元素的个数

归并排序

参考剑指 Offer 51. 数组中的逆序对 - 力扣(LeetCode) (leetcode-cn.com)

重点是被排序过程中的数字下标的对应,这里取了一个index数列,在排序的同时进行移动,从而保证下标对应

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
class Solution {
public:
vector<int> countSmaller(vector<int>& nums) {
int n = nums.size();
tmp.resize(n);
index.resize(n);
indextmp.resize(n);
ret.resize(n);
for(int i = 0; i < n; ++i)
index[i] = i;
mergeSort(nums, 0, n - 1);
return ret;
}
private:
vector<int> ret;
vector<int> tmp;
vector<int> index;
vector<int> indextmp;
void mergeSort(vector<int>& nums, int lo, int hi)
{
if(lo >= hi)
return;
int mid = lo + (hi - lo) / 2;
mergeSort(nums, lo, mid);
mergeSort(nums, mid + 1, hi);
copy(nums.begin() + lo, nums.begin() + hi + 1, tmp.begin() + lo);
copy(index.begin() + lo, index.begin() + hi + 1, indextmp.begin() + lo);
int i = lo, j = mid + 1, k = lo;
while(k <= hi)
{
if(i == mid + 1)
{
nums[k] = tmp[j];
index[k] = indextmp[j++];
}else if(j == hi + 1)
{
ret[indextmp[i]] += j - mid - 1; // 当i这个数要进去坐牢,j这边已经进去的数都比他小,所以共j-mid-1个,当前j是hi+1,所以不包含j
nums[k] = tmp[i];
index[k] = indextmp[i++];
}
else if(tmp[i] <= tmp[j])
{
ret[indextmp[i]] += j - mid - 1; // 当i这个数要进去坐牢,j这边已经进去的数都比他小,所以共j-mid-1个,当前这边大于等于i那边的数,所以不包含j
nums[k] = tmp[i];
index[k] = indextmp[i++];
}else
{
nums[k] = tmp[j];
index[k] = indextmp[j++];
}
++k;
}
}
};
离散化树状数组

迟点看 https://www.cnblogs.com/xenny/p/9739600.html

https://leetcode-cn.com/problems/count-of-smaller-numbers-after-self/solution/shu-zhuang-shu-zu-by-liweiwei1419/